bug fix with default rank

This commit is contained in:
2026-05-29 13:29:56 -04:00
parent 3b023d3c6b
commit 77641ecefd
4 changed files with 107 additions and 0 deletions
@@ -2,6 +2,7 @@ package net.kewwbec.ranks;
import com.hypixel.hytale.logger.HytaleLogger; import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.core.event.events.player.PlayerChatEvent; import com.hypixel.hytale.server.core.event.events.player.PlayerChatEvent;
import com.hypixel.hytale.server.core.event.events.player.PlayerConnectEvent;
import com.hypixel.hytale.server.core.permissions.PermissionsModule; import com.hypixel.hytale.server.core.permissions.PermissionsModule;
import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider; import com.hypixel.hytale.server.core.permissions.provider.PermissionProvider;
import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPlugin;
@@ -9,6 +10,9 @@ import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import net.kewwbec.networkcore.NetworkCore; import net.kewwbec.networkcore.NetworkCore;
import net.kewwbec.networkcore.api.DatabaseService; import net.kewwbec.networkcore.api.DatabaseService;
import net.kewwbec.networkcore.api.MessageBus; import net.kewwbec.networkcore.api.MessageBus;
import net.kewwbec.networkcore.api.ranks.RankInfo;
import net.kewwbec.networkcore.api.ranks.RankLookup;
import net.kewwbec.ranks.model.Rank;
import net.kewwbec.ranks.command.GrantCommands; import net.kewwbec.ranks.command.GrantCommands;
import net.kewwbec.ranks.command.rank.RankCommand; import net.kewwbec.ranks.command.rank.RankCommand;
import net.kewwbec.ranks.config.RanksConfig; import net.kewwbec.ranks.config.RanksConfig;
@@ -18,6 +22,7 @@ import net.kewwbec.ranks.db.RankRepository;
import net.kewwbec.ranks.db.SchemaBootstrap; import net.kewwbec.ranks.db.SchemaBootstrap;
import net.kewwbec.ranks.db.UserPermRepository; import net.kewwbec.ranks.db.UserPermRepository;
import net.kewwbec.ranks.listener.ChatPrefixListener; import net.kewwbec.ranks.listener.ChatPrefixListener;
import net.kewwbec.ranks.listener.DefaultRankAssigner;
import net.kewwbec.ranks.provider.RanksPermissionProvider; import net.kewwbec.ranks.provider.RanksPermissionProvider;
import net.kewwbec.ranks.service.RankService; import net.kewwbec.ranks.service.RankService;
import net.kewwbec.ranks.service.RanksCache; import net.kewwbec.ranks.service.RanksCache;
@@ -104,9 +109,24 @@ public final class RanksPlugin extends JavaPlugin {
RankService service = new RankService(rankRepo, grantRepo, userPermRepo, cache); RankService service = new RankService(rankRepo, grantRepo, userPermRepo, cache);
RankLookup lookup = uuid -> {
try {
Rank r = service.getPrimaryRank(uuid);
if (r == null) return null;
return new RankInfo(r.id(), r.displayName(), r.prefix(), r.color());
} catch (SQLException e) {
LOGGER.at(Level.WARNING).log("RankLookup failed for %s: %s", uuid, e.getMessage());
return null;
}
};
core.registerService(RankLookup.class, lookup);
ChatPrefixListener prefixListener = new ChatPrefixListener(service, config.chat); ChatPrefixListener prefixListener = new ChatPrefixListener(service, config.chat);
getEventRegistry().registerGlobal(PlayerChatEvent.class, prefixListener::onChat); getEventRegistry().registerGlobal(PlayerChatEvent.class, prefixListener::onChat);
DefaultRankAssigner defaultAssigner = new DefaultRankAssigner(service, config.defaults);
getEventRegistry().registerGlobal(PlayerConnectEvent.class, defaultAssigner::onConnect);
getCommandRegistry().registerCommand(new RankCommand(service)); getCommandRegistry().registerCommand(new RankCommand(service));
getCommandRegistry().registerCommand(new GrantCommands.Grant(service)); getCommandRegistry().registerCommand(new GrantCommands.Grant(service));
getCommandRegistry().registerCommand(new GrantCommands.TempGrant(service)); getCommandRegistry().registerCommand(new GrantCommands.TempGrant(service));
@@ -6,6 +6,7 @@ public final class RanksConfig {
public ProviderSection provider = new ProviderSection(); public ProviderSection provider = new ProviderSection();
public ChatSection chat = new ChatSection(); public ChatSection chat = new ChatSection();
public CacheSection cache = new CacheSection(); public CacheSection cache = new CacheSection();
public DefaultsSection defaults = new DefaultsSection();
public static final class TableSection { public static final class TableSection {
public String ranks = "ranks"; public String ranks = "ranks";
@@ -33,6 +34,23 @@ public final class RanksConfig {
public String prefix_format = "{prefix} "; public String prefix_format = "{prefix} ";
} }
public static final class DefaultsSection {
/**
* Rank id every player gets on first connect if they have no active grants. Also promoted
* to primary if the player has no primary rank yet. Set null/blank to disable.
*/
public String default_rank_id = "hytale:None";
/**
* UUID used as the "granted_by" actor for system-issued default grants. Use a stable
* non-real UUID so audit queries can identify these.
*/
public String system_actor_uuid = "00000000-0000-0000-0000-000000000000";
/**
* Display name for the system actor.
*/
public String system_actor_name = "SYSTEM";
}
public static final class CacheSection { public static final class CacheSection {
/** /**
* Channel used to broadcast cache-invalidation messages across servers. * Channel used to broadcast cache-invalidation messages across servers.
@@ -32,6 +32,7 @@ public final class RanksConfigLoader {
if (parsed.provider == null) parsed.provider = new RanksConfig.ProviderSection(); if (parsed.provider == null) parsed.provider = new RanksConfig.ProviderSection();
if (parsed.chat == null) parsed.chat = new RanksConfig.ChatSection(); if (parsed.chat == null) parsed.chat = new RanksConfig.ChatSection();
if (parsed.cache == null) parsed.cache = new RanksConfig.CacheSection(); if (parsed.cache == null) parsed.cache = new RanksConfig.CacheSection();
if (parsed.defaults == null) parsed.defaults = new RanksConfig.DefaultsSection();
return parsed; return parsed;
} }
} }
@@ -0,0 +1,68 @@
package net.kewwbec.ranks.listener;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.core.event.events.player.PlayerConnectEvent;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import net.kewwbec.ranks.config.RanksConfig;
import net.kewwbec.ranks.service.RankService;
import javax.annotation.Nonnull;
import java.sql.SQLException;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
/**
* On PlayerConnectEvent: if the player has no active rank grants, grant them the configured
* default rank (e.g. {@code hytale:None}). If they have grants but no primary rank set, promote
* the default (when present in their active grants) to primary.
*
* Idempotent: a player with existing grants is left alone. Race-tolerant: if two servers see the
* connect at the same time, both attempt a grant; the cache invalidation cleans it up and the
* surplus grant is harmless (still maps to the same primary rank).
*/
public final class DefaultRankAssigner {
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
private final RankService service;
private final RanksConfig.DefaultsSection cfg;
private final UUID systemActor;
public DefaultRankAssigner(@Nonnull RankService service, @Nonnull RanksConfig.DefaultsSection cfg) {
this.service = service;
this.cfg = cfg;
UUID parsed;
try { parsed = UUID.fromString(cfg.system_actor_uuid); }
catch (RuntimeException e) { parsed = new UUID(0L, 0L); }
this.systemActor = parsed;
}
public void onConnect(@Nonnull PlayerConnectEvent event) {
if (cfg.default_rank_id == null || cfg.default_rank_id.isBlank()) return;
PlayerRef ref = event.getPlayerRef();
if (ref == null) return;
UUID uuid = ref.getUuid();
String name = ref.getUsername();
try {
Set<String> active = service.getActiveRankIds(uuid);
if (active.isEmpty()) {
long id = service.grant(uuid, cfg.default_rank_id, systemActor, cfg.system_actor_name, null);
if (id > 0) {
service.setPrimary(uuid, cfg.default_rank_id);
LOGGER.at(Level.INFO).log("Granted default rank '%s' to %s (%s)", cfg.default_rank_id, name, uuid);
} else {
LOGGER.at(Level.WARNING).log("Default rank '%s' not found in DB; cannot grant to %s", cfg.default_rank_id, name);
}
return;
}
String primary = service.getPrimaryRankId(uuid);
if (primary == null && active.contains(cfg.default_rank_id)) {
service.setPrimary(uuid, cfg.default_rank_id);
}
} catch (SQLException e) {
((HytaleLogger.Api) LOGGER.at(Level.WARNING).withCause(e))
.log("Default rank assignment failed for %s", uuid);
}
}
}