Skip to content
Open
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
Empty file modified gradlew
100644 → 100755
Empty file.
2 changes: 2 additions & 0 deletions src/main/java/com/blbilink/blbilogin/BlbiLogin.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@

public final class BlbiLogin extends JavaPlugin implements Listener {
public static BlbiLogin plugin;
public static long serverStartTime;
public I18n i18n;
public ConfigUtil config;
public FoliaUtil foliaUtil;

@Override
public void onEnable() {
plugin = this;
serverStartTime = System.currentTimeMillis();

// Initialize plugin
LoadConfig.loadConfig(this);
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/blbilink/blbilogin/load/LoadFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,17 @@ private void loadCommands(){
Objects.requireNonNull(plugin.getCommand("kill")).setExecutor(new KillCommand());
Objects.requireNonNull(plugin.getCommand("worldstats")).setExecutor(new WorldStatsCommand());
Objects.requireNonNull(plugin.getCommand("info")).setExecutor(new InfoCommand());
Objects.requireNonNull(plugin.getCommand("stats")).setExecutor(new StatsCommand());
Objects.requireNonNull(plugin.getCommand("dupe")).setExecutor(new DupeCommand());
Objects.requireNonNull(plugin.getCommand("tpa")).setExecutor(new TpaCommand());
Objects.requireNonNull(plugin.getCommand("tphere")).setExecutor(new TphereCommand());
Objects.requireNonNull(plugin.getCommand("tpaccept")).setExecutor(new TpacceptCommand());
Objects.requireNonNull(plugin.getCommand("tpacancel")).setExecutor(new TpacancelCommand());
Objects.requireNonNull(plugin.getCommand("joindate")).setExecutor(new JoinDateCommand());
Objects.requireNonNull(plugin.getCommand("playtime")).setExecutor(new PlayTimeCommand());
Objects.requireNonNull(plugin.getCommand("listplayers")).setExecutor(new ListPlayersCommand());
Objects.requireNonNull(plugin.getCommand("tpoffline")).setExecutor(new TpOfflineCommand());
Objects.requireNonNull(plugin.getCommand("blacklist")).setExecutor(new BlacklistCommand());
}
private void loadListeners(){
// Register Bukkit event listeners
Expand All @@ -55,6 +62,7 @@ private void loadListeners(){
Bukkit.getPluginManager().registerEvents(new com.blbilink.blbilogin.modules.dupe.ChestBoatDupeListener(0), plugin);
Bukkit.getPluginManager().registerEvents(new com.blbilink.blbilogin.modules.events.SpamProtection(), plugin);
Bukkit.getPluginManager().registerEvents(new com.blbilink.blbilogin.modules.events.WitherSkullExplodeFix(), plugin);
Bukkit.getPluginManager().registerEvents(new com.blbilink.blbilogin.modules.events.ChatFilter(), plugin);
}

private void loadSqlite(){
Expand Down
144 changes: 143 additions & 1 deletion src/main/java/com/blbilink/blbilogin/modules/Sqlite.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ public Sqlite() {
try (PreparedStatement statement = connection.prepareStatement("CREATE TABLE IF NOT EXISTS players (uuid TEXT PRIMARY KEY, username TEXT, password TEXT)")) {
statement.executeUpdate();
}
try (PreparedStatement statement = connection.prepareStatement(
"CREATE TABLE IF NOT EXISTS playerdata (" +
"uuid TEXT PRIMARY KEY," +
"firstJoin INTEGER," +
"joinCount INTEGER," +
"logoutWorld TEXT," +
"logoutX REAL," +
"logoutY REAL," +
"logoutZ REAL," +
"logoutYaw REAL," +
"logoutPitch REAL," +
"blacklist INTEGER DEFAULT 0" +
")")) {
statement.executeUpdate();
}
} catch (SQLException e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -73,4 +88,131 @@ public boolean resetPassword(String uuid, String newPassword) {
}
return false;
}
}

public void recordJoin(String uuid) {
try (PreparedStatement select = connection.prepareStatement("SELECT joinCount FROM playerdata WHERE uuid = ?")) {
select.setString(1, uuid);
ResultSet rs = select.executeQuery();
if (rs.next()) {
int count = rs.getInt("joinCount") + 1;
try (PreparedStatement update = connection.prepareStatement("UPDATE playerdata SET joinCount = ? WHERE uuid = ?")) {
update.setInt(1, count);
update.setString(2, uuid);
update.executeUpdate();
}
} else {
try (PreparedStatement insert = connection.prepareStatement("INSERT INTO playerdata (uuid, firstJoin, joinCount) VALUES (?, ?, 1)")) {
insert.setString(1, uuid);
insert.setLong(2, System.currentTimeMillis());
insert.executeUpdate();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}

public int getJoinCount(String uuid) {
try (PreparedStatement statement = connection.prepareStatement("SELECT joinCount FROM playerdata WHERE uuid = ?")) {
statement.setString(1, uuid);
ResultSet rs = statement.executeQuery();
if (rs.next()) {
return rs.getInt("joinCount");
}
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

public Long getFirstJoin(String uuid) {
try (PreparedStatement statement = connection.prepareStatement("SELECT firstJoin FROM playerdata WHERE uuid = ?")) {
statement.setString(1, uuid);
ResultSet rs = statement.executeQuery();
if (rs.next()) {
return rs.getLong("firstJoin");
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}

public void setLogoutLocation(String uuid, org.bukkit.Location loc) {
try (PreparedStatement statement = connection.prepareStatement(
"INSERT INTO playerdata (uuid, logoutWorld, logoutX, logoutY, logoutZ, logoutYaw, logoutPitch) " +
"VALUES (?, ?, ?, ?, ?, ?, ?) " +
"ON CONFLICT(uuid) DO UPDATE SET logoutWorld=excluded.logoutWorld, logoutX=excluded.logoutX, " +
"logoutY=excluded.logoutY, logoutZ=excluded.logoutZ, logoutYaw=excluded.logoutYaw, logoutPitch=excluded.logoutPitch")) {
statement.setString(1, uuid);
statement.setString(2, loc.getWorld().getName());
statement.setDouble(3, loc.getX());
statement.setDouble(4, loc.getY());
statement.setDouble(5, loc.getZ());
statement.setFloat(6, loc.getYaw());
statement.setFloat(7, loc.getPitch());
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}

public org.bukkit.Location getLogoutLocation(String uuid) {
try (PreparedStatement statement = connection.prepareStatement("SELECT logoutWorld, logoutX, logoutY, logoutZ, logoutYaw, logoutPitch FROM playerdata WHERE uuid = ?")) {
statement.setString(1, uuid);
ResultSet rs = statement.executeQuery();
if (rs.next() && rs.getString("logoutWorld") != null) {
org.bukkit.World world = org.bukkit.Bukkit.getWorld(rs.getString("logoutWorld"));
if (world != null) {
return new org.bukkit.Location(world,
rs.getDouble("logoutX"),
rs.getDouble("logoutY"),
rs.getDouble("logoutZ"),
rs.getFloat("logoutYaw"),
rs.getFloat("logoutPitch"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}

public boolean isBlacklisted(String uuid) {
try (PreparedStatement statement = connection.prepareStatement("SELECT blacklist FROM playerdata WHERE uuid = ?")) {
statement.setString(1, uuid);
ResultSet rs = statement.executeQuery();
if (rs.next()) {
return rs.getInt("blacklist") == 1;
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}

public void setBlacklisted(String uuid, boolean value) {
try (PreparedStatement statement = connection.prepareStatement(
"INSERT INTO playerdata (uuid, blacklist) VALUES (?, ?) " +
"ON CONFLICT(uuid) DO UPDATE SET blacklist=excluded.blacklist")) {
statement.setString(1, uuid);
statement.setInt(2, value ? 1 : 0);
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}

public java.util.List<String> listUsernames() {
java.util.List<String> list = new java.util.ArrayList<>();
try (PreparedStatement statement = connection.prepareStatement("SELECT username FROM players ORDER BY username ASC")) {
ResultSet rs = statement.executeQuery();
while (rs.next()) {
list.add(rs.getString("username"));
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.blbilink.blbilogin.modules.commands;

import com.blbilink.blbilogin.modules.Sqlite;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;


public class BlacklistCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player) || !player.isOp()) {
sender.sendMessage("Only operators can use this command");
return true;
}
if (args.length != 1) {
player.sendMessage("/blacklist <username>");
return true;
}
OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]);
Sqlite.getSqlite().setBlacklisted(target.getUniqueId().toString(), true);
if (target.isOnline()) {
((Player) target).kickPlayer("Disconnected: Internal server error");
}
player.sendMessage(target.getName() + " has been blacklisted");
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.blbilink.blbilogin.load.LoadConfig;
import com.blbilink.blbilogin.vars.Configvar;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
Expand Down Expand Up @@ -38,17 +39,36 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
}

private void reload(CommandSender sender) {
if ((sender instanceof Player player)) {
if (player.hasPermission("blbilogin.reload")) {
LoadConfig.loadConfig(plugin);
player.sendMessage(plugin.i18n.as("msgReloaded", true, player.getName()));
} else {
player.sendMessage(plugin.i18n.as("msgNoPermission", true, player.getName()));
}
} else {
LoadConfig.loadConfig(plugin);
plugin.getLogger().info(plugin.i18n.as("msgReloaded", false));
boolean allowed = !(sender instanceof Player p) || p.hasPermission("blbilogin.reload");
if (!allowed) {
((Player) sender).sendMessage(plugin.i18n.as("msgNoPermission", true, ((Player) sender).getName()));
return;
}

// Schedule reload so we don't disable the plugin while handling the command
Bukkit.getScheduler().runTask(plugin, () -> {
try {
java.io.File file = new java.io.File(plugin.getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
org.bukkit.plugin.PluginManager pm = Bukkit.getPluginManager();

pm.disablePlugin(plugin);

org.bukkit.plugin.Plugin loaded = ((org.bukkit.plugin.SimplePluginManager) pm).loadPlugin(file);
loaded.onLoad();
pm.enablePlugin(loaded);

// Use the newly enabled instance for messages
BlbiLogin newPlugin = BlbiLogin.plugin;
if (sender instanceof Player player) {
player.sendMessage(newPlugin.i18n.as("msgReloaded", true, player.getName()));
} else {
newPlugin.getLogger().info(newPlugin.i18n.as("msgReloaded", false));
}
} catch (Exception e) {
BlbiLogin.plugin.getLogger().severe("Failed to reload plugin: " + e.getMessage());
e.printStackTrace();
}
});
}

private void saveLocation(CommandSender sender) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
package com.blbilink.blbilogin.modules.commands;

import com.blbilink.blbilogin.BlbiLogin;
import com.blbilink.blbilogin.modules.Sqlite;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;

public class InfoCommand extends WorldStatsCommand implements CommandExecutor {
import java.lang.management.ManagementFactory;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatter;


public class InfoCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return super.onCommand(sender, command, label, args);
if (args.length != 1) {
sender.sendMessage("/info <player>");
return true;
}
OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]);
if (!target.hasPlayedBefore() && !target.isOnline()) {
sender.sendMessage("Player not found");
return true;
}
String uuid = target.getUniqueId().toString();
int joins = Sqlite.getSqlite().getJoinCount(uuid);
if (joins == 0) {
joins = target.getStatistic(Statistic.LEAVE_GAME) + 1;
}
long serverUptime = System.currentTimeMillis() - BlbiLogin.serverStartTime;
long osUptime = System.currentTimeMillis() - ManagementFactory.getRuntimeMXBean().getStartTime();
Long first = Sqlite.getSqlite().getFirstJoin(uuid);
if (first == null) first = target.getFirstPlayed();
String firstJoined = first > 0 ? DateTimeFormatter.ISO_LOCAL_DATE.format(Instant.ofEpochMilli(first)) : "Unknown";
String msg = String.format("%s has joined %d times. First join: %s", target.getName(), joins, firstJoined);
String serverUp = formatDuration(serverUptime);
String osUp = formatDuration(osUptime);
sender.sendMessage(msg);
sender.sendMessage("Server uptime: " + serverUp);
sender.sendMessage("System uptime: " + osUp);
return true;
}

private String formatDuration(long millis) {
Duration d = Duration.ofMillis(millis);
long days = d.toDays();
long hours = d.minusDays(days).toHours();
long minutes = d.minusDays(days).minusHours(hours).toMinutes();
return days + "d " + hours + "h " + minutes + "m";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.blbilink.blbilogin.modules.commands;

import com.blbilink.blbilogin.modules.Sqlite;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;

import java.time.Instant;
import java.time.format.DateTimeFormatter;

public class JoinDateCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
String targetName = args.length > 0 ? args[0] : sender.getName();
OfflinePlayer target = Bukkit.getOfflinePlayerIfCached(targetName);
if (target == null) target = Bukkit.getPlayerExact(targetName);
if (target == null || (!target.hasPlayedBefore() && !target.isOnline())) {
sender.sendMessage("Player not found");
return true;
}
Long ts = Sqlite.getSqlite().getFirstJoin(target.getUniqueId().toString());
if (ts == null) ts = target.getFirstPlayed();
String date = ts > 0 ? DateTimeFormatter.ISO_LOCAL_DATE.format(Instant.ofEpochMilli(ts)) : "Unknown";
sender.sendMessage(target.getName() + " first joined on " + date);
return true;
}
}
Loading
Loading