Move files around
This commit is contained in:
parent
d3838f6a78
commit
1592d0b2a4
242 changed files with 13063 additions and 0 deletions
|
|
@ -0,0 +1,127 @@
|
|||
package me.alexdevs.solstice.modules;
|
||||
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.api.module.ModuleEntrypoint;
|
||||
import me.alexdevs.solstice.modules.admin.AdminModule;
|
||||
import me.alexdevs.solstice.modules.afk.AfkModule;
|
||||
import me.alexdevs.solstice.modules.autoAnnouncement.AutoAnnouncementModule;
|
||||
import me.alexdevs.solstice.modules.item.ItemModule;
|
||||
import me.alexdevs.solstice.modules.jail.JailModule;
|
||||
import me.alexdevs.solstice.modules.kit.KitModule;
|
||||
import me.alexdevs.solstice.modules.miscellaneous.MiscellaneousModule;
|
||||
import me.alexdevs.solstice.modules.note.NoteModule;
|
||||
import me.alexdevs.solstice.modules.notifications.NotificationsModule;
|
||||
import me.alexdevs.solstice.modules.placeholders.PlaceholdersModule;
|
||||
import me.alexdevs.solstice.modules.powertool.PowerToolModule;
|
||||
import me.alexdevs.solstice.modules.restart.RestartModule;
|
||||
import me.alexdevs.solstice.modules.back.BackModule;
|
||||
import me.alexdevs.solstice.modules.ban.BanModule;
|
||||
import me.alexdevs.solstice.modules.broadcast.BroadcastModule;
|
||||
import me.alexdevs.solstice.modules.commandSpy.CommandSpyModule;
|
||||
import me.alexdevs.solstice.modules.customName.CustomNameModule;
|
||||
import me.alexdevs.solstice.modules.enderchest.EnderChestModule;
|
||||
import me.alexdevs.solstice.modules.experiments.ExperimentsModule;
|
||||
import me.alexdevs.solstice.modules.extinguish.ExtinguishModule;
|
||||
import me.alexdevs.solstice.modules.feed.FeedModule;
|
||||
import me.alexdevs.solstice.modules.fly.FlyModule;
|
||||
import me.alexdevs.solstice.modules.rtp.RTPModule;
|
||||
import me.alexdevs.solstice.modules.sign.SignModule;
|
||||
import me.alexdevs.solstice.modules.god.GodModule;
|
||||
import me.alexdevs.solstice.modules.hat.HatModule;
|
||||
import me.alexdevs.solstice.modules.heal.HealModule;
|
||||
import me.alexdevs.solstice.modules.helpOp.HelpOpModule;
|
||||
import me.alexdevs.solstice.modules.home.HomeModule;
|
||||
import me.alexdevs.solstice.modules.ignite.IgniteModule;
|
||||
import me.alexdevs.solstice.modules.ignore.IgnoreModule;
|
||||
import me.alexdevs.solstice.modules.info.InfoModule;
|
||||
import me.alexdevs.solstice.modules.inventorySee.InventorySeeModule;
|
||||
import me.alexdevs.solstice.modules.kick.KickModule;
|
||||
import me.alexdevs.solstice.modules.mail.MailModule;
|
||||
import me.alexdevs.solstice.modules.mute.MuteModule;
|
||||
import me.alexdevs.solstice.modules.near.NearModule;
|
||||
import me.alexdevs.solstice.modules.seen.SeenModule;
|
||||
import me.alexdevs.solstice.modules.skull.SkullModule;
|
||||
import me.alexdevs.solstice.modules.smite.SmiteModule;
|
||||
import me.alexdevs.solstice.modules.spawn.SpawnModule;
|
||||
import me.alexdevs.solstice.modules.staffChat.StaffChatModule;
|
||||
import me.alexdevs.solstice.modules.styling.StylingModule;
|
||||
import me.alexdevs.solstice.modules.sudo.SudoModule;
|
||||
import me.alexdevs.solstice.modules.suicide.SuicideModule;
|
||||
import me.alexdevs.solstice.modules.tablist.TabListModule;
|
||||
import me.alexdevs.solstice.modules.teleportHere.TeleportHereModule;
|
||||
import me.alexdevs.solstice.modules.teleportOffline.TeleportOfflineModule;
|
||||
import me.alexdevs.solstice.modules.teleportPosition.TeleportPositionModule;
|
||||
import me.alexdevs.solstice.modules.teleportRequest.TeleportRequestModule;
|
||||
import me.alexdevs.solstice.modules.tell.TellModule;
|
||||
import me.alexdevs.solstice.modules.timeBar.TimeBarModule;
|
||||
import me.alexdevs.solstice.modules.trash.TrashModule;
|
||||
import me.alexdevs.solstice.modules.utilities.UtilitiesModule;
|
||||
import me.alexdevs.solstice.modules.warp.WarpModule;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class ModuleProvider implements ModuleEntrypoint {
|
||||
private static final List<? extends ModuleBase> modules = List.of(
|
||||
new AdminModule(),
|
||||
new AfkModule(),
|
||||
new AutoAnnouncementModule(),
|
||||
new RestartModule(),
|
||||
new BackModule(),
|
||||
new BanModule(),
|
||||
new BroadcastModule(),
|
||||
new CommandSpyModule(),
|
||||
new CustomNameModule(),
|
||||
new EnderChestModule(),
|
||||
new ExperimentsModule(),
|
||||
new ExtinguishModule(),
|
||||
new FeedModule(),
|
||||
new FlyModule(),
|
||||
new SignModule(),
|
||||
new GodModule(),
|
||||
new HatModule(),
|
||||
new HealModule(),
|
||||
new HelpOpModule(),
|
||||
new HomeModule(),
|
||||
new IgniteModule(),
|
||||
new IgnoreModule(),
|
||||
new InfoModule(),
|
||||
new InventorySeeModule(),
|
||||
new ItemModule(),
|
||||
new JailModule(),
|
||||
new KickModule(),
|
||||
new KitModule(),
|
||||
new MailModule(),
|
||||
new MiscellaneousModule(),
|
||||
new MuteModule(),
|
||||
new NearModule(),
|
||||
new NoteModule(),
|
||||
new NotificationsModule(),
|
||||
new PlaceholdersModule(),
|
||||
new PowerToolModule(),
|
||||
new RTPModule(),
|
||||
new SeenModule(),
|
||||
new SkullModule(),
|
||||
new SmiteModule(),
|
||||
new SpawnModule(),
|
||||
new StaffChatModule(),
|
||||
new StylingModule(),
|
||||
new SudoModule(),
|
||||
new SuicideModule(),
|
||||
new TabListModule(),
|
||||
new TeleportHereModule(),
|
||||
new TeleportOfflineModule(),
|
||||
new TeleportPositionModule(),
|
||||
new TeleportRequestModule(),
|
||||
new TellModule(),
|
||||
new TimeBarModule(),
|
||||
new TrashModule(),
|
||||
new UtilitiesModule(),
|
||||
new WarpModule()
|
||||
);
|
||||
|
||||
@Override
|
||||
public HashSet<ModuleBase> register() {
|
||||
return new HashSet<>(modules);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package me.alexdevs.solstice.modules.admin;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.events.PlayerConnectionEvents;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
|
||||
public class AdminModule extends ModuleBase {
|
||||
public static final String ID = "admin";
|
||||
|
||||
public AdminModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
PlayerConnectionEvents.WHITELIST_BYPASS.register(profile -> {
|
||||
try {
|
||||
return Permissions.check(profile, getWhitelistBypassPermission(), false).get();
|
||||
} catch (Exception e) {
|
||||
Solstice.LOGGER.error("Error checking whitelist bypass for profile {}", profile.getId(), e);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
PlayerConnectionEvents.FULL_SERVER_BYPASS.register(profile -> {
|
||||
try {
|
||||
return Permissions.check(profile, getFullServerBypassPermission(), false).get();
|
||||
} catch (Exception e) {
|
||||
Solstice.LOGGER.error("Error checking full server bypass for profile {}", profile.getId(), e);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public String getWhitelistBypassPermission() {
|
||||
return getPermissionNode("bypass.whitelist");
|
||||
}
|
||||
|
||||
public String getFullServerBypassPermission() {
|
||||
return getPermissionNode("bypass.fullserver");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,361 @@
|
|||
package me.alexdevs.solstice.modules.afk;
|
||||
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import eu.pb4.placeholders.api.PlaceholderResult;
|
||||
import eu.pb4.placeholders.api.Placeholders;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.api.events.CommandEvents;
|
||||
import me.alexdevs.solstice.api.events.PlayerActivityEvents;
|
||||
import me.alexdevs.solstice.api.events.SolsticeEvents;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import me.alexdevs.solstice.modules.afk.commands.ActiveTimeCommand;
|
||||
import me.alexdevs.solstice.modules.afk.commands.AfkCommand;
|
||||
import me.alexdevs.solstice.modules.afk.data.*;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.player.*;
|
||||
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AfkModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "afk";
|
||||
|
||||
public static final double sprintSpeed = 0.280617;
|
||||
public static final double walkSpeed = 0.215859;
|
||||
public static final double sneakSpeed = 0.0841;
|
||||
|
||||
public static final int LEADERBOARD_SIZE = 10;
|
||||
|
||||
public enum AfkTriggerReason {
|
||||
MANUAL,
|
||||
MOVEMENT,
|
||||
LOOK_CHANGE,
|
||||
CHAT_MESSAGE,
|
||||
COMMAND,
|
||||
BLOCK_ATTACK,
|
||||
BLOCK_INTERACT,
|
||||
ENTITY_ATTACK,
|
||||
ENTITY_INTERACT,
|
||||
ITEM_USE,
|
||||
}
|
||||
|
||||
private final Map<UUID, PlayerActivityState> activities = new ConcurrentHashMap<>();
|
||||
|
||||
public AfkModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, AfkConfig.class, AfkConfig::new);
|
||||
Solstice.localeManager.registerModule(ID, AfkLocale.MODULE);
|
||||
Solstice.playerData.registerData(ID, AfkPlayerData.class, AfkPlayerData::new);
|
||||
Solstice.serverData.registerData(ID, AfkServerData.class, AfkServerData::new);
|
||||
|
||||
this.commands.add(new AfkCommand(this));
|
||||
this.commands.add(new ActiveTimeCommand(this));
|
||||
|
||||
Placeholders.register(ResourceLocation.fromNamespaceAndPath(Solstice.MOD_ID, "afk"), (context, arg) -> {
|
||||
if (!context.hasPlayer())
|
||||
return PlaceholderResult.invalid("No player!");
|
||||
|
||||
var player = context.player();
|
||||
|
||||
if (isPlayerAfk(player))
|
||||
return PlaceholderResult.value(Format.parse(getConfig().tag));
|
||||
else
|
||||
return PlaceholderResult.value("");
|
||||
});
|
||||
|
||||
SolsticeEvents.READY.register((instance, server) -> {
|
||||
Solstice.scheduler.scheduleAtFixedRate(this::updateActiveTime, 0, 1, TimeUnit.SECONDS);
|
||||
calculateLeaderboard();
|
||||
});
|
||||
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
activities.put(handler.getPlayer().getUUID(), new PlayerActivityState(handler.getPlayer(), server.getTickCount()));
|
||||
});
|
||||
|
||||
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
||||
activities.remove(handler.getPlayer().getUUID());
|
||||
});
|
||||
|
||||
ServerTickEvents.END_SERVER_TICK.register(this::tick);
|
||||
|
||||
PlayerActivityEvents.AFK.register((player) -> {
|
||||
var config = getConfig();
|
||||
|
||||
if (player.serverLevel().canSleepThroughNights()) {
|
||||
player.serverLevel().updateSleepingPlayerList();
|
||||
}
|
||||
|
||||
Solstice.LOGGER.info("{} is AFK. Active time: {} seconds.", player.getGameProfile().getName(), getActiveTime(player.getUUID()));
|
||||
if (!config.announce)
|
||||
return;
|
||||
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
Solstice.getInstance().broadcast(locale().get("goneAfk", playerContext));
|
||||
});
|
||||
|
||||
PlayerActivityEvents.AFK_RETURN.register((player, reason) -> {
|
||||
var config = getConfig();
|
||||
|
||||
if (player.serverLevel().canSleepThroughNights()) {
|
||||
player.serverLevel().updateSleepingPlayerList();
|
||||
}
|
||||
|
||||
Solstice.LOGGER.info("{} is no longer AFK due to {}. Active time: {} seconds.", player.getGameProfile().getName(), reason.name(), getActiveTime(player.getUUID()));
|
||||
if (!config.announce)
|
||||
return;
|
||||
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
Solstice.getInstance().broadcast(locale().get("returnAfk", playerContext));
|
||||
});
|
||||
|
||||
registerTriggers();
|
||||
}
|
||||
|
||||
public AfkServerData getServerData() {
|
||||
return Solstice.serverData.getData(AfkServerData.class);
|
||||
}
|
||||
|
||||
private void updateActiveTime() {
|
||||
var activePlayers = Solstice.server.getPlayerList().getPlayers()
|
||||
.stream().filter(player -> !isPlayerAfk(player));
|
||||
|
||||
activePlayers.forEach(player -> {
|
||||
var activity = activities.computeIfAbsent(player.getUUID(), uuid -> new PlayerActivityState(player, player.getServer().getTickCount()));
|
||||
if (!activity.activeTimeEnabled)
|
||||
return;
|
||||
|
||||
var playerData = getPlayerData(player.getUUID());
|
||||
playerData.activeTime++;
|
||||
tryInsertLeaderboard(player, playerData.activeTime);
|
||||
});
|
||||
}
|
||||
|
||||
private void tryInsertLeaderboard(ServerPlayer player, int activeTime) {
|
||||
var serverData = getServerData();
|
||||
var leaderboard = serverData.leaderboard;
|
||||
|
||||
// if in list, update
|
||||
var entry = leaderboard.stream().filter(e -> e.uuid().equals(player.getUUID())).findFirst();
|
||||
if (entry.isPresent()) {
|
||||
entry.get().activeTime(activeTime);
|
||||
entry.get().name(player.getGameProfile().getName());
|
||||
leaderboard.sort((o1, o2) -> Integer.compare(o2.activeTime(), o1.activeTime()));
|
||||
return;
|
||||
}
|
||||
|
||||
// if not in list, insert
|
||||
var smallest = leaderboard.stream().min(Comparator.comparingInt(LeaderboardEntry::activeTime));
|
||||
if (smallest.isPresent()) {
|
||||
if (smallest.get().activeTime() < activeTime) {
|
||||
leaderboard.remove(smallest.get());
|
||||
leaderboard.add(new LeaderboardEntry(player.getGameProfile().getName(), player.getUUID(), activeTime));
|
||||
leaderboard.sort((o1, o2) -> Integer.compare(o2.activeTime(), o1.activeTime()));
|
||||
}
|
||||
} else {
|
||||
leaderboard.add(new LeaderboardEntry(player.getGameProfile().getName(), player.getUUID(), activeTime));
|
||||
}
|
||||
}
|
||||
|
||||
private void tick(MinecraftServer server) {
|
||||
var config = getConfig();
|
||||
if (!config.enable)
|
||||
return;
|
||||
|
||||
server.getPlayerList().getPlayers().forEach(player -> {
|
||||
var activity = activities.computeIfAbsent(player.getUUID(), uuid -> new PlayerActivityState(player, server.getTickCount()));
|
||||
|
||||
var curLocation = new ServerLocation(player);
|
||||
var oldLocation = activity.location;
|
||||
activity.location = curLocation;
|
||||
|
||||
var delta = curLocation.getDelta(oldLocation);
|
||||
var horizontalDelta = new Vec3(delta.x(), 0, delta.z());
|
||||
|
||||
var speed = horizontalDelta.length();
|
||||
|
||||
// Suppose the player in a vehicle will look around, so we only check for movement when not in a vehicle.
|
||||
if (player.getVehicle() == null) {
|
||||
// Defeats some anti-afk stuff, like pools. Works best when no lag.
|
||||
if ((player.isShiftKeyDown() && speed >= sneakSpeed) || (player.isSprinting() && speed >= sprintSpeed) || (speed >= walkSpeed)) {
|
||||
if (getConfig().triggers.onMovement) {
|
||||
clearAfk(player, AfkTriggerReason.MOVEMENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Looking around requires player input
|
||||
if (curLocation.getPitch() != oldLocation.getPitch() || curLocation.getYaw() != oldLocation.getYaw()) {
|
||||
if (getConfig().triggers.onLookChange) {
|
||||
clearAfk(player, AfkTriggerReason.LOOK_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
var ticks = server.getTickCount();
|
||||
if (activity.lastUpdate < ticks - config.timeTrigger * 20) {
|
||||
if (!activity.isAfk && activity.afkEnabled) {
|
||||
activity.isAfk = true;
|
||||
PlayerActivityEvents.AFK.invoker().onAfk(player);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public AfkConfig getConfig() {
|
||||
return Solstice.configManager.getData(AfkConfig.class);
|
||||
}
|
||||
|
||||
public AfkPlayerData getPlayerData(UUID playerUuid) {
|
||||
return Solstice.playerData.get(playerUuid).getData(AfkPlayerData.class);
|
||||
}
|
||||
|
||||
public boolean isPlayerAfk(ServerPlayer player) {
|
||||
return activities.containsKey(player.getUUID()) && activities.get(player.getUUID()).isAfk;
|
||||
}
|
||||
|
||||
public void setPlayerAfk(ServerPlayer player, boolean isAfk) {
|
||||
if (!activities.containsKey(player.getUUID()))
|
||||
return;
|
||||
|
||||
var config = getConfig();
|
||||
var activity = activities.get(player.getUUID());
|
||||
if (isAfk) {
|
||||
activity.lastUpdate = activity.lastUpdate - (config.timeTrigger * 20);
|
||||
} else {
|
||||
clearAfk(player, AfkTriggerReason.MANUAL);
|
||||
}
|
||||
}
|
||||
|
||||
public int getActiveTime(UUID playerUuid) {
|
||||
return getPlayerData(playerUuid).activeTime;
|
||||
}
|
||||
|
||||
private void calculateLeaderboard() {
|
||||
var serverData = getServerData();
|
||||
if (!serverData.forceCalculateLeaderboard)
|
||||
return;
|
||||
|
||||
serverData.forceCalculateLeaderboard = false;
|
||||
|
||||
var userCache = Solstice.getUserCache();
|
||||
var temp = new ArrayList<LeaderboardEntry>();
|
||||
for (var name : userCache.getAllNames()) {
|
||||
var profile = userCache.getByName(name);
|
||||
if (profile.isEmpty())
|
||||
continue;
|
||||
|
||||
var playerData = Solstice.playerData.get(profile.get().getId()).getData(AfkPlayerData.class);
|
||||
if (playerData.activeTime > 0) {
|
||||
var entry = new LeaderboardEntry(profile.get().getName(), profile.get().getId(), playerData.activeTime);
|
||||
temp.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
temp.sort((o1, o2) -> Integer.compare(o2.activeTime(), o1.activeTime()));
|
||||
|
||||
serverData.leaderboard.clear();
|
||||
|
||||
for (var i = 0; i < Math.min(temp.size(), LEADERBOARD_SIZE); i++) {
|
||||
serverData.leaderboard.add(temp.get(i));
|
||||
}
|
||||
|
||||
var onlinePlayers = Solstice.server.getPlayerList().getPlayers().stream().map(Entity::getUUID).toList();
|
||||
Solstice.playerData.disposeMissing(onlinePlayers);
|
||||
}
|
||||
|
||||
public List<LeaderboardEntry> getActiveTimeLeaderboard() {
|
||||
var serverData = getServerData();
|
||||
return Collections.unmodifiableList(serverData.leaderboard);
|
||||
}
|
||||
|
||||
public List<ServerPlayer> getCurrentActivePlayers() {
|
||||
return Solstice.server.getPlayerList().getPlayers().stream().filter(player -> !isPlayerAfk(player)).toList();
|
||||
}
|
||||
|
||||
private void clearAfk(ServerPlayer player, AfkTriggerReason reason) {
|
||||
if (!activities.containsKey(player.getUUID()))
|
||||
return;
|
||||
|
||||
var activity = activities.get(player.getUUID());
|
||||
activity.lastUpdate = Solstice.server.getTickCount();
|
||||
|
||||
if (!activity.afkEnabled)
|
||||
return;
|
||||
|
||||
if (activity.isAfk) {
|
||||
activity.isAfk = false;
|
||||
PlayerActivityEvents.AFK_RETURN.invoker().onAfkReturn(player, reason);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void registerTriggers() {
|
||||
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
|
||||
if (getConfig().triggers.onBlockAttack) {
|
||||
clearAfk((ServerPlayer) player, AfkTriggerReason.BLOCK_ATTACK);
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> {
|
||||
if (getConfig().triggers.onEntityAttack) {
|
||||
clearAfk((ServerPlayer) player, AfkTriggerReason.ENTITY_ATTACK);
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> {
|
||||
if (getConfig().triggers.onBlockInteract) {
|
||||
clearAfk((ServerPlayer) player, AfkTriggerReason.BLOCK_INTERACT);
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> {
|
||||
if (getConfig().triggers.onEntityInteract) {
|
||||
clearAfk((ServerPlayer) player, AfkTriggerReason.ENTITY_INTERACT);
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
UseItemCallback.EVENT.register((player, world, hand) -> {
|
||||
if (getConfig().triggers.onItemUse) {
|
||||
clearAfk((ServerPlayer) player, AfkTriggerReason.ITEM_USE);
|
||||
}
|
||||
return InteractionResultHolder.pass(player.getItemInHand(hand));
|
||||
});
|
||||
|
||||
ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, sender, params) -> {
|
||||
if (getConfig().triggers.onChat) {
|
||||
clearAfk(sender, AfkTriggerReason.CHAT_MESSAGE);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
CommandEvents.ALLOW_COMMAND.register((source, command) -> {
|
||||
if (!source.isPlayer())
|
||||
return true;
|
||||
|
||||
if (getConfig().triggers.onCommand) {
|
||||
clearAfk(source.getPlayer(), AfkTriggerReason.COMMAND);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
package me.alexdevs.solstice.modules.afk.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.command.TimeSpan;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.afk.AfkModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ActiveTimeCommand extends ModCommand<AfkModule> {
|
||||
public ActiveTimeCommand(AfkModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("activetime");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var activeTime = module.getActiveTime(player.getUUID());
|
||||
|
||||
var longSpan = TimeSpan.toLongString(activeTime);
|
||||
|
||||
var map = Map.of(
|
||||
"activeTime", Component.nullToEmpty(longSpan),
|
||||
"player", player.getName()
|
||||
);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("yourActiveTime", map), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
.then(Commands.literal("player")
|
||||
.requires(require("others", 1))
|
||||
.then(Commands.argument("player", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> {
|
||||
var profile = LocalGameProfile.getProfile(context, "player");
|
||||
var activeTime = module.getActiveTime(profile.getId());
|
||||
|
||||
if (activeTime == 0) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("neverPlayed"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var longSpan = TimeSpan.toLongString(activeTime);
|
||||
|
||||
var map = Map.of(
|
||||
"activeTime", Component.nullToEmpty(longSpan),
|
||||
"player", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("playerActiveTime", map), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
))
|
||||
.then(Commands.literal("leaderboard")
|
||||
.requires(require("leaderboard", true))
|
||||
.executes(context -> {
|
||||
var leaderboard = module.getActiveTimeLeaderboard();
|
||||
|
||||
var text = Component.empty();
|
||||
|
||||
text.append(module.locale().get("leaderboardHeader"));
|
||||
|
||||
var index = 0;
|
||||
for (var entry : leaderboard) {
|
||||
text.append("\n");
|
||||
index++;
|
||||
var map = Map.of(
|
||||
"index", Component.nullToEmpty(String.valueOf(index)),
|
||||
"player", Component.nullToEmpty(entry.name()),
|
||||
"uuid", Component.nullToEmpty(entry.uuid().toString()),
|
||||
"time", Component.nullToEmpty(TimeSpan.toLongString(entry.activeTime())),
|
||||
"shortTime", Component.nullToEmpty(TimeSpan.toShortString(entry.activeTime())),
|
||||
"seconds", Component.nullToEmpty(String.valueOf(entry.activeTime()))
|
||||
);
|
||||
text.append(module.locale().get("leaderboardEntry", map));
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() -> text, false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
)
|
||||
.then(Commands.literal("set")
|
||||
.requires(require("set", 3))
|
||||
.then(Commands.argument("player", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.then(Commands.argument("time", TimeSpan.timeSpan())
|
||||
.suggests(TimeSpan::suggest)
|
||||
.executes(context -> {
|
||||
var profile = LocalGameProfile.getProfile(context, "player");
|
||||
var time = TimeSpan.getTimeSpan(context, "time");
|
||||
|
||||
var data = module.getPlayerData(profile.getId());
|
||||
data.activeTime = time;
|
||||
|
||||
var map = Map.of(
|
||||
"player", Component.nullToEmpty(profile.getName()),
|
||||
"time", Component.nullToEmpty(TimeSpan.toLongString(time))
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get("activeTimeSet", map), true);
|
||||
|
||||
return 1;
|
||||
})
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package me.alexdevs.solstice.modules.afk.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.afk.AfkModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class AfkCommand extends ModCommand<AfkModule> {
|
||||
public AfkCommand(AfkModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("afk");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
|
||||
module.setPlayerAfk(player, !module.isPlayerAfk(player));
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package me.alexdevs.solstice.modules.afk.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ConfigSerializable
|
||||
public class AfkConfig {
|
||||
@Comment("Enable the AFK functionality. Requires server restart.")
|
||||
public boolean enable = true;
|
||||
|
||||
@Comment("Announce in chat when a player goes or return from AFK.")
|
||||
public boolean announce = true;
|
||||
|
||||
@Comment("AFK triggers after the player has been inactive for the following seconds. Defaults to 300 seconds.")
|
||||
public int timeTrigger = 300;
|
||||
|
||||
@Comment("This tag is displayed with `solstice:afk` placeholder when the player is AFK.")
|
||||
public String tag = "<gray>[AFK]</gray> ";
|
||||
|
||||
@Comment("These triggers clear the AFK status. Events regarding entities, blocks or item usage may be triggered by fake players.")
|
||||
public AfkTriggers triggers = new AfkTriggers();
|
||||
|
||||
@ConfigSerializable
|
||||
public static class AfkTriggers {
|
||||
@Comment("Movement is triggered when the velocity threshold is met.")
|
||||
public boolean onMovement = true;
|
||||
|
||||
@Comment("Look change is triggered when the player yaw and/or pitch change.")
|
||||
public boolean onLookChange = true;
|
||||
|
||||
@Comment("Trigger on chat messages sent by the player.")
|
||||
public boolean onChat = true;
|
||||
|
||||
@Comment("Trigger on commands.")
|
||||
public boolean onCommand = true;
|
||||
|
||||
@Comment("Trigger when a block is being attacked (left click).")
|
||||
public boolean onBlockAttack = true;
|
||||
|
||||
@Comment("Trigger when a block is being interacted with (right click).")
|
||||
public boolean onBlockInteract = true;
|
||||
|
||||
@Comment("Trigger when an entity is attacked.")
|
||||
public boolean onEntityAttack = true;
|
||||
|
||||
@Comment("Trigger when an entity is interacted with.")
|
||||
public boolean onEntityInteract = true;
|
||||
|
||||
@Comment("Trigger when an item is used.")
|
||||
public boolean onItemUse = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package me.alexdevs.solstice.modules.afk.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class AfkLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("goneAfk", "<gray>%player:displayname% is now AFK</gray>"),
|
||||
Map.entry("returnAfk", "<gray>%player:displayname% is no longer AFK</gray>"),
|
||||
Map.entry("yourActiveTime", "<gold>Your active time is <yellow>${activeTime}</yellow>.</gold>"),
|
||||
Map.entry("playerActiveTime", "<gold><yellow>${player}</yellow>'s active time is <yellow>${activeTime}</yellow>.</gold>"),
|
||||
Map.entry("neverPlayed", "<gold>This player never played.</gold>"),
|
||||
Map.entry("notFound", "<gold>Player not found.</gold>"),
|
||||
Map.entry("leaderboardHeader", "<gold>Active Time Leaderboard:</gold>"),
|
||||
Map.entry("leaderboardEntry", "<gold> <gold>${index}.</gold> <yellow>${player}</yellow>: <gray>${time}</gray></gold>"),
|
||||
Map.entry("activeTimeSet", "<gold>Set <yellow>${player}</yellow>'s active time to <yellow>${time}</yellow>!</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package me.alexdevs.solstice.modules.afk.data;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
||||
public class AfkPlayerData {
|
||||
@Expose
|
||||
public int activeTime = 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package me.alexdevs.solstice.modules.afk.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class AfkServerData {
|
||||
public boolean forceCalculateLeaderboard = true;
|
||||
public List<LeaderboardEntry> leaderboard = new ArrayList<>();
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package me.alexdevs.solstice.modules.afk.data;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class LeaderboardEntry {
|
||||
protected String name;
|
||||
protected final UUID uuid;
|
||||
protected int activeTime;
|
||||
|
||||
public LeaderboardEntry(String name, UUID uuid, int activeTime) {
|
||||
this.name = name;
|
||||
this.uuid = uuid;
|
||||
this.activeTime = activeTime;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void name(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UUID uuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public int activeTime() {
|
||||
return activeTime;
|
||||
}
|
||||
|
||||
public void activeTime(int activeTime) {
|
||||
this.activeTime = activeTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package me.alexdevs.solstice.modules.afk.data;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.modules.afk.AfkModule;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
||||
public class PlayerActivityState {
|
||||
public ServerLocation location;
|
||||
public int lastUpdate;
|
||||
public boolean isAfk;
|
||||
public boolean afkEnabled;
|
||||
public boolean activeTimeEnabled;
|
||||
|
||||
public PlayerActivityState(ServerPlayer player, int lastUpdate) {
|
||||
this.location = new ServerLocation(player);
|
||||
this.lastUpdate = lastUpdate;
|
||||
this.isAfk = false;
|
||||
this.afkEnabled = Permissions.check(player, Solstice.MOD_ID + "." + AfkModule.ID + ".base", true);
|
||||
this.activeTimeEnabled = Permissions.check(player, Solstice.MOD_ID + "." + AfkModule.ID + ".activetime", true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package me.alexdevs.solstice.modules.autoAnnouncement;
|
||||
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.events.SolsticeEvents;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import me.alexdevs.solstice.modules.autoAnnouncement.data.AutoAnnouncementConfig;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AutoAnnouncementModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "autoannouncement";
|
||||
|
||||
private ScheduledFuture<?> scheduledFuture = null;
|
||||
private int currentLine = 0;
|
||||
|
||||
public AutoAnnouncementModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, AutoAnnouncementConfig.class, AutoAnnouncementConfig::new);
|
||||
|
||||
SolsticeEvents.READY.register((instance, server) -> {
|
||||
setup();
|
||||
});
|
||||
|
||||
SolsticeEvents.RELOAD.register(instance -> {
|
||||
if (scheduledFuture != null) {
|
||||
scheduledFuture.cancel(false);
|
||||
}
|
||||
setup();
|
||||
});
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
currentLine = 0;
|
||||
if (getConfig().enable) {
|
||||
scheduledFuture = Solstice.scheduler.scheduleAtFixedRate(this::announce, getConfig().delay, getConfig().delay, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public AutoAnnouncementConfig getConfig() {
|
||||
return Solstice.configManager.getData(AutoAnnouncementConfig.class);
|
||||
}
|
||||
|
||||
public void announce() {
|
||||
var lines = getConfig().announcements;
|
||||
if (lines.isEmpty())
|
||||
return;
|
||||
|
||||
if (getConfig().pickRandomly) {
|
||||
currentLine = new Random().nextInt(lines.size());
|
||||
}
|
||||
|
||||
currentLine %= lines.size();
|
||||
var line = lines.get(currentLine);
|
||||
currentLine++;
|
||||
|
||||
Solstice.server.getPlayerList().getPlayers().forEach(player -> {
|
||||
if (line.permission() != null) {
|
||||
var result = line.result();
|
||||
if (result == null)
|
||||
result = true;
|
||||
if (Permissions.check(player, line.permission()) != result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
player.sendSystemMessage(Format.parse(line.text(), playerContext));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package me.alexdevs.solstice.modules.autoAnnouncement.data;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class AutoAnnouncementConfig {
|
||||
@Comment("Enable automatic announcements functionality.")
|
||||
public boolean enable = true;
|
||||
@Comment("Pick the next announcement randomly, else linearly.")
|
||||
public boolean pickRandomly = false;
|
||||
// every 5 mins
|
||||
@Comment("Send announcement every X seconds. Defaults to 300 seconds.")
|
||||
public int delay = 300;
|
||||
@Comment("Announcement list. Announcements can have a permission as condition. If result is true, the permission has to be granted, else the permission has to be denied (or unset).")
|
||||
public ArrayList<Announcement> announcements = new ArrayList<>(List.of(
|
||||
new Announcement("Tip! <gray>Solstice is open-source! Contribute on <url:'https://github.com/Ale32bit/Solstice'><blue>GitHub</blue></url>!</gray>"),
|
||||
new Announcement("Fun fact! <gray>This announcement is only visible to players that do not have the 'solstice.example' permission granted!</gray>", "solstice.example", false)
|
||||
));
|
||||
|
||||
@ConfigSerializable
|
||||
public record Announcement(String text, @Nullable String permission, @Nullable Boolean result) {
|
||||
public Announcement(String text) {
|
||||
this(text, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package me.alexdevs.solstice.modules.back;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.api.events.PlayerTeleportCallback;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.back.commands.BackCommand;
|
||||
import me.alexdevs.solstice.modules.back.data.BackLocale;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BackModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "back";
|
||||
public final ConcurrentHashMap<UUID, ServerLocation> lastPlayerPositions = new ConcurrentHashMap<>();
|
||||
|
||||
public BackModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, BackLocale.MODULE);
|
||||
|
||||
commands.add(new BackCommand(this));
|
||||
|
||||
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> lastPlayerPositions.remove(handler.getPlayer().getUUID()));
|
||||
|
||||
PlayerTeleportCallback.EVENT.register((player, origin, destination) -> lastPlayerPositions.put(player.getUUID(), origin));
|
||||
|
||||
ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> {
|
||||
if (entity.isAlwaysTicking()) {
|
||||
try {
|
||||
var player = (ServerPlayer) entity;
|
||||
lastPlayerPositions.put(entity.getUUID(), new ServerLocation(player));
|
||||
} catch (ClassCastException e) {
|
||||
// They were, in fact, not a player.
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package me.alexdevs.solstice.modules.back.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.locale.Locale;
|
||||
import me.alexdevs.solstice.modules.back.BackModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class BackCommand extends ModCommand<BackModule> {
|
||||
private final Locale locale = Solstice.localeManager.getLocale(BackModule.ID);
|
||||
|
||||
public BackCommand(BackModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("back");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
var lastPosition = module.lastPlayerPositions.get(player.getUUID());
|
||||
if (lastPosition == null) {
|
||||
context.getSource().sendSuccess(() -> locale.get(
|
||||
"noPosition",
|
||||
playerContext
|
||||
), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() -> locale.get(
|
||||
"teleporting",
|
||||
playerContext
|
||||
), false);
|
||||
lastPosition.teleport(player);
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package me.alexdevs.solstice.modules.back.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BackLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("teleporting", "<gold>Teleporting to previous position...</gold>"),
|
||||
Map.entry("noPosition", "<red>There is no position to return back to.</red>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package me.alexdevs.solstice.modules.ban;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.ban.commands.BanCommand;
|
||||
import me.alexdevs.solstice.modules.ban.commands.TempBanCommand;
|
||||
import me.alexdevs.solstice.modules.ban.commands.UnbanCommand;
|
||||
import me.alexdevs.solstice.modules.ban.data.BanLocale;
|
||||
|
||||
public class BanModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "ban";
|
||||
|
||||
public BanModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, BanLocale.MODULE);
|
||||
|
||||
commands.add(new BanCommand(this));
|
||||
commands.add(new TempBanCommand(this));
|
||||
commands.add(new UnbanCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package me.alexdevs.solstice.modules.ban.commands;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.module.Utils;
|
||||
import me.alexdevs.solstice.modules.ban.BanModule;
|
||||
import me.alexdevs.solstice.modules.ban.formatters.BanMessageFormatter;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.arguments.GameProfileArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.ComponentUtils;
|
||||
import net.minecraft.server.players.UserBanListEntry;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class BanCommand extends ModCommand<BanModule> {
|
||||
public static final SimpleCommandExceptionType ALREADY_BANNED_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.ban.failed"));
|
||||
|
||||
public BanCommand(BanModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
static int execute(CommandContext<CommandSourceStack> context, Collection<GameProfile> targets, @Nullable String reason, @Nullable Date expiryDate) throws CommandSyntaxException {
|
||||
var source = context.getSource();
|
||||
var server = source.getServer();
|
||||
var banList = server.getPlayerList().getBans();
|
||||
|
||||
var banCounter = 0;
|
||||
for (GameProfile target : targets) {
|
||||
if (banList.isBanned(target)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var banEntry = new UserBanListEntry(target, null, source.getTextName(), expiryDate, reason);
|
||||
banList.add(banEntry);
|
||||
banCounter++;
|
||||
|
||||
var playerContext = PlaceholderContext.of(target, server);
|
||||
|
||||
source.sendSuccess(() -> Component.translatable("commands.ban.success", Component.nullToEmpty(target.getName()), Format.parse(banEntry.getReason(), playerContext)), true);
|
||||
|
||||
var serverPlayerEntity = source.getServer().getPlayerList().getPlayer(target.getId());
|
||||
if (serverPlayerEntity != null) {
|
||||
serverPlayerEntity.connection.disconnect(BanMessageFormatter.format(target, banEntry));
|
||||
}
|
||||
}
|
||||
|
||||
if (banCounter == 0) {
|
||||
throw ALREADY_BANNED_EXCEPTION.create();
|
||||
} else {
|
||||
return banCounter;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext commandRegistry, Commands.CommandSelection environment) {
|
||||
Utils.removeCommands(dispatcher, "ban");
|
||||
super.register(dispatcher, commandRegistry, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("ban");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(3))
|
||||
.then(argument("targets", GameProfileArgument.gameProfile())
|
||||
.executes(context -> execute(context, GameProfileArgument.getGameProfiles(context, "targets"), null, null))
|
||||
.then(argument("reason", StringArgumentType.greedyString())
|
||||
.executes(context -> execute(context, GameProfileArgument.getGameProfiles(context, "targets"), StringArgumentType.getString(context, "reason"), null))));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package me.alexdevs.solstice.modules.ban.commands;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.command.TimeSpan;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.ban.BanModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.GameProfileArgument;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class TempBanCommand extends ModCommand<BanModule> {
|
||||
public TempBanCommand(BanModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
private static Date getDateFromNow(int seconds) {
|
||||
var now = new Date();
|
||||
var c = Calendar.getInstance();
|
||||
c.setTime(now);
|
||||
c.add(Calendar.SECOND, seconds);
|
||||
return c.getTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("tempban");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require("tempban", 3))
|
||||
.then(argument("targets", GameProfileArgument.gameProfile())
|
||||
.then(argument("duration", StringArgumentType.string())
|
||||
.suggests(TimeSpan::suggest)
|
||||
.executes(context -> execute(context, GameProfileArgument.getGameProfiles(context, "targets"), null, TimeSpan.getTimeSpan(context, "duration")))
|
||||
.then(argument("reason", StringArgumentType.greedyString())
|
||||
.executes(context -> execute(context, GameProfileArgument.getGameProfiles(context, "targets"), StringArgumentType.getString(context, "reason"), TimeSpan.getTimeSpan(context, "duration"))))));
|
||||
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, Collection<GameProfile> targets, String reason, int duration) throws CommandSyntaxException {
|
||||
var expiryDate = getDateFromNow(duration);
|
||||
|
||||
return BanCommand.execute(context, targets, reason, expiryDate);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package me.alexdevs.solstice.modules.ban.commands;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.module.Utils;
|
||||
import me.alexdevs.solstice.modules.ban.BanModule;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.commands.arguments.GameProfileArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.ComponentUtils;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class UnbanCommand extends ModCommand<BanModule> {
|
||||
private static final SimpleCommandExceptionType ALREADY_UNBANNED_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.pardon.failed"));
|
||||
|
||||
public UnbanCommand(BanModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext commandRegistry, Commands.CommandSelection environment) {
|
||||
Utils.removeCommands(dispatcher, "pardon");
|
||||
super.register(dispatcher, commandRegistry, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("unban", "pardon");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(3))
|
||||
.then(Commands.argument("targets", GameProfileArgument.gameProfile())
|
||||
.suggests((context, builder) -> SharedSuggestionProvider.suggest((context.getSource()).getServer().getPlayerList().getBans().getUserList(), builder))
|
||||
.executes(context -> execute(context, GameProfileArgument.getGameProfiles(context, "targets"))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, Collection<GameProfile> targets) throws CommandSyntaxException {
|
||||
var banList = context.getSource().getServer().getPlayerList().getBans();
|
||||
var source = context.getSource();
|
||||
var pardonCount = 0;
|
||||
for (GameProfile profile : targets) {
|
||||
if (banList.isBanned(profile)) {
|
||||
banList.remove(profile);
|
||||
pardonCount++;
|
||||
source.sendSuccess(() -> Component.translatable("commands.pardon.success", Component.nullToEmpty(profile.getName())), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pardonCount == 0) {
|
||||
throw ALREADY_UNBANNED_EXCEPTION.create();
|
||||
} else {
|
||||
return pardonCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package me.alexdevs.solstice.modules.ban.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BanLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("banMessageFormat", "<red>You are banned from this server:</red>\n\n${reason}"),
|
||||
Map.entry("tempBanMessageFormat", "<red>You are temporarily banned from this server:</red>\n\n${reason}\n\n<gray>Expires: ${expiry_date}</gray>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package me.alexdevs.solstice.modules.ban.formatters;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.modules.ban.BanModule;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.players.UserBanListEntry;
|
||||
import me.alexdevs.solstice.core.coreModule.CoreModule;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Map;
|
||||
|
||||
public class BanMessageFormatter {
|
||||
public static Component format(GameProfile profile, UserBanListEntry entry) {
|
||||
var locale = Solstice.modules.getModule(BanModule.class).locale();
|
||||
var coreConfig = CoreModule.getConfig();
|
||||
var df = new SimpleDateFormat(coreConfig.dateTimeFormat);
|
||||
|
||||
var context = PlaceholderContext.of(profile, Solstice.server);
|
||||
var expiryDate = Component.nullToEmpty(entry.getExpires() != null ? df.format(entry.getExpires()) : "never");
|
||||
Map<String, Component> placeholders = Map.of(
|
||||
"reason", Format.parse(entry.getReason(), context),
|
||||
"creation_date", Component.nullToEmpty(df.format(entry.getCreated())),
|
||||
"expiry_date", expiryDate,
|
||||
"source", Component.nullToEmpty(entry.getSource())
|
||||
);
|
||||
|
||||
var format = entry.getExpires() != null ? locale.raw("tempBanMessageFormat") : locale.raw("banMessageFormat");
|
||||
|
||||
return Format.parse(format, context, placeholders);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package me.alexdevs.solstice.modules.broadcast;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.broadcast.commands.BroadcastCommand;
|
||||
import me.alexdevs.solstice.modules.broadcast.commands.PlainBroadcastCommand;
|
||||
import me.alexdevs.solstice.modules.broadcast.data.BroadcastConfig;
|
||||
|
||||
public class BroadcastModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "broadcast";
|
||||
|
||||
public BroadcastModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, BroadcastConfig.class, BroadcastConfig::new);
|
||||
|
||||
commands.add(new BroadcastCommand(this));
|
||||
commands.add(new PlainBroadcastCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package me.alexdevs.solstice.modules.broadcast.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.broadcast.BroadcastModule;
|
||||
import me.alexdevs.solstice.modules.broadcast.data.BroadcastConfig;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class BroadcastCommand extends ModCommand<BroadcastModule> {
|
||||
|
||||
public BroadcastCommand(BroadcastModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("broadcast", "bc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.then(argument("message", StringArgumentType.greedyString())
|
||||
.executes(context -> {
|
||||
var config = Solstice.configManager.getData(BroadcastConfig.class);
|
||||
|
||||
var message = StringArgumentType.getString(context, "message");
|
||||
var serverContext = PlaceholderContext.of(context.getSource().getServer());
|
||||
|
||||
var placeholders = Map.of(
|
||||
"message", Format.parse(message, serverContext)
|
||||
);
|
||||
|
||||
Solstice.getInstance().broadcast(Format.parse(config.format, placeholders));
|
||||
|
||||
return 1;
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package me.alexdevs.solstice.modules.broadcast.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.broadcast.BroadcastModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class PlainBroadcastCommand extends ModCommand<BroadcastModule> {
|
||||
|
||||
public PlainBroadcastCommand(BroadcastModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("plainbroadcast", "pbc");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require("plain", 2))
|
||||
.then(argument("message", StringArgumentType.greedyString())
|
||||
.executes(context -> {
|
||||
var message = StringArgumentType.getString(context, "message");
|
||||
var serverContext = PlaceholderContext.of(context.getSource().getServer());
|
||||
|
||||
Solstice.getInstance().broadcast(Format.parse(message, serverContext));
|
||||
|
||||
return 1;
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package me.alexdevs.solstice.modules.broadcast.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ConfigSerializable
|
||||
public class BroadcastConfig {
|
||||
@Comment("Format to use when broadcasting a message.")
|
||||
public String format = "<red>[</red><gold>Broadcast</gold><red>]</red> ${message}";
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package me.alexdevs.solstice.modules.commandSpy;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.events.CommandEvents;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.commandSpy.data.CommandSpyConfig;
|
||||
import me.alexdevs.solstice.modules.commandSpy.data.CommandSpyLocale;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandSpyModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "commandspy";
|
||||
|
||||
public CommandSpyModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, CommandSpyConfig.class, CommandSpyConfig::new);
|
||||
Solstice.localeManager.registerModule(ID, CommandSpyLocale.MODULE);
|
||||
|
||||
CommandEvents.ALLOW_COMMAND.register((source, command) -> {
|
||||
if (!source.isPlayer())
|
||||
return true;
|
||||
|
||||
Solstice.LOGGER.info("{}: /{}", source.getTextName(), command);
|
||||
|
||||
var parts = command.split("\\s");
|
||||
if (parts.length >= 1) {
|
||||
var cmd = parts[0];
|
||||
if (isIgnored(cmd)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var player = source.getPlayer();
|
||||
|
||||
var players = source.getServer().getPlayerList().getPlayers();
|
||||
var placeholders = Map.of("player", Component.nullToEmpty(player.getGameProfile().getName()), "command", Component.nullToEmpty(command));
|
||||
var message = locale().get("spyFormat", placeholders);
|
||||
for (var pl : players) {
|
||||
var commandSpyEnabled = Permissions.check(pl, this.getPermissionNode("base"));
|
||||
|
||||
if (commandSpyEnabled && !pl.getUUID().equals(player.getUUID())) {
|
||||
pl.displayClientMessage(message, false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public boolean isIgnored(String command) {
|
||||
if(!isEnabled())
|
||||
return false;
|
||||
|
||||
return Solstice.configManager.getData(CommandSpyConfig.class).ignoredCommands.contains(command);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package me.alexdevs.solstice.modules.commandSpy.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class CommandSpyConfig {
|
||||
@Comment("Commands to ignore.")
|
||||
public ArrayList<String> ignoredCommands = new ArrayList<>(List.of(
|
||||
"tell", "w", "msg", "dm", "r", "staffchat", "sc", "helpop", "sos"
|
||||
));
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package me.alexdevs.solstice.modules.commandSpy.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandSpyLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("spyFormat", "\uD83D\uDC41 <dark_gray>${player}:</dark_gray> <gray>/${command}</gray>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package me.alexdevs.solstice.modules.customName;
|
||||
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import me.alexdevs.solstice.api.text.RawPlaceholder;
|
||||
import me.alexdevs.solstice.integrations.LuckPermsIntegration;
|
||||
import me.alexdevs.solstice.modules.customName.commands.NicknameCommand;
|
||||
import me.alexdevs.solstice.modules.customName.data.CustomNameConfig;
|
||||
import me.alexdevs.solstice.modules.customName.data.CustomNamePlayerData;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import java.util.Map;
|
||||
|
||||
public class CustomNameModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "customname";
|
||||
|
||||
public CustomNameModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, CustomNameConfig.class, CustomNameConfig::new);
|
||||
Solstice.playerData.registerData(ID, CustomNamePlayerData.class, CustomNamePlayerData::new);
|
||||
|
||||
commands.add(new NicknameCommand(this));
|
||||
}
|
||||
|
||||
public String fetchUsernameFormat(ServerPlayer player) {
|
||||
var formats = Solstice.configManager.getData(CustomNameConfig.class).nameFormats;
|
||||
|
||||
String format = null;
|
||||
for (var f : formats) {
|
||||
if (LuckPermsIntegration.isInGroup(player, f.group())) {
|
||||
format = f.format();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var isOperator = player.getServer().getPlayerList().isOp(player.getGameProfile());
|
||||
|
||||
if (format == null) {
|
||||
format = "${username}";
|
||||
|
||||
for (var f : formats) {
|
||||
if (isOperator && f.group().equals("operator")) {
|
||||
format = f.format();
|
||||
break;
|
||||
}
|
||||
if (f.group().equals("default")) {
|
||||
format = f.format();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
public String getResolvedUsername(ServerPlayer player) {
|
||||
var format = fetchUsernameFormat(player);
|
||||
var playerData = Solstice.playerData.get(player).getData(CustomNamePlayerData.class);
|
||||
var name = playerData.nickname == null ? player.getGameProfile().getName() : playerData.nickname;
|
||||
|
||||
var prefix = LuckPermsIntegration.getPrefix(player);
|
||||
var suffix = LuckPermsIntegration.getSuffix(player);
|
||||
if (prefix == null)
|
||||
prefix = "";
|
||||
if (suffix == null)
|
||||
suffix = "";
|
||||
|
||||
Map<String, String> placeholders = Map.of(
|
||||
"name", name,
|
||||
"prefix", prefix,
|
||||
"suffix", suffix
|
||||
);
|
||||
|
||||
return RawPlaceholder.parse(format, placeholders);
|
||||
}
|
||||
|
||||
public MutableComponent getNameForPlayer(ServerPlayer player) {
|
||||
var name = getResolvedUsername(player);
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
return Format.parse(name, playerContext).copy();
|
||||
}
|
||||
|
||||
public void setCustomName(ServerPlayer player, String name) {
|
||||
var playerData = Solstice.playerData.get(player).getData(CustomNamePlayerData.class);
|
||||
playerData.nickname = name;
|
||||
}
|
||||
|
||||
public void clearCustomName(ServerPlayer player) {
|
||||
var playerData = Solstice.playerData.get(player).getData(CustomNamePlayerData.class);
|
||||
playerData.nickname = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package me.alexdevs.solstice.modules.customName.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.customName.CustomNameModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class NicknameCommand extends ModCommand<CustomNameModule> {
|
||||
|
||||
public NicknameCommand(CustomNameModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("nickname", "nick");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.then(literal("clear")
|
||||
.executes(context -> executeClear(context, null))
|
||||
)
|
||||
.then(argument("nickname", StringArgumentType.string())
|
||||
.executes(context -> execute(context, StringArgumentType.getString(context, "nickname"), null))
|
||||
)
|
||||
.then(argument("player", EntityArgument.player())
|
||||
.requires(require("others", 2))
|
||||
.then(literal("clear")
|
||||
.executes(context -> executeClear(context, EntityArgument.getPlayer(context, "player")))
|
||||
)
|
||||
.then(argument("nickname", StringArgumentType.string())
|
||||
.executes(context -> execute(context, StringArgumentType.getString(context, "nickname"), EntityArgument.getPlayer(context, "player")))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, String nickname, @Nullable ServerPlayer player) throws CommandSyntaxException {
|
||||
if (player == null) {
|
||||
player = context.getSource().getPlayerOrException();
|
||||
}
|
||||
|
||||
module.setCustomName(player, nickname);
|
||||
|
||||
var name = player.getGameProfile().getName();
|
||||
context.getSource().sendSuccess(() -> Component.literal(String.format("Changed %s's nickname", name)), true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int executeClear(CommandContext<CommandSourceStack> context, @Nullable ServerPlayer player) throws CommandSyntaxException {
|
||||
if (player == null) {
|
||||
player = context.getSource().getPlayerOrException();
|
||||
}
|
||||
|
||||
module.clearCustomName(player);
|
||||
|
||||
var name = player.getGameProfile().getName();
|
||||
context.getSource().sendSuccess(() -> Component.literal(String.format("Cleared %s's nickname", name)), true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package me.alexdevs.solstice.modules.customName.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class CustomNameConfig {
|
||||
@Comment("Customize player display names based on their LuckPerms group. Priority is determined by the list order: first comes before last.")
|
||||
public ArrayList<NameFormat> nameFormats = new ArrayList<>(List.of(
|
||||
new NameFormat("admin", "${prefix}<red>${name}</red>${suffix}"),
|
||||
new NameFormat("default", "${prefix}<green>${name}</green>${suffix}")
|
||||
));
|
||||
|
||||
@ConfigSerializable
|
||||
public record NameFormat(String group, String format) {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package me.alexdevs.solstice.modules.customName.data;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CustomNamePlayerData {
|
||||
public @Nullable String nickname;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package me.alexdevs.solstice.modules.enderchest;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.enderchest.commands.EnderChestCommand;
|
||||
import me.alexdevs.solstice.modules.enderchest.data.EnderChestLocale;
|
||||
|
||||
public class EnderChestModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "enderchest";
|
||||
|
||||
public EnderChestModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, EnderChestLocale.LOCALE);
|
||||
|
||||
commands.add(new EnderChestCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
package me.alexdevs.solstice.modules.enderchest.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.utils.PlayerUtils;
|
||||
import me.alexdevs.solstice.modules.enderchest.EnderChestModule;
|
||||
import me.alexdevs.solstice.modules.inventorySee.ImmutableSlot;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.stats.Stats;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.inventory.PlayerEnderChestContainer;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class EnderChestCommand extends ModCommand<EnderChestModule> {
|
||||
public EnderChestCommand(EnderChestModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("enderchest", "ec");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||
|
||||
open(player, player.getEnderChestInventory(), Component.translatable("container.enderchest"), true, () -> {
|
||||
});
|
||||
|
||||
return 1;
|
||||
})
|
||||
.then(argument("player", StringArgumentType.word())
|
||||
.requires(require("others", 2))
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> {
|
||||
final var source = context.getSource();
|
||||
var player = source.getPlayerOrException();
|
||||
var profile = LocalGameProfile.getProfile(context, "player");
|
||||
|
||||
Permissions.check(profile, getPermissionNode("exempt"), 3, source.getServer()).thenAccept(exempt -> {
|
||||
if (exempt) {
|
||||
source.sendSuccess(() -> module.locale().get("exempt"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
var isOnline = PlayerUtils.isOnline(profile.getId());
|
||||
if (!isOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) {
|
||||
source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
ServerPlayer targetPlayer;
|
||||
|
||||
if (isOnline) {
|
||||
targetPlayer = source.getServer().getPlayerList().getPlayer(profile.getId());
|
||||
} else {
|
||||
targetPlayer = PlayerUtils.loadOfflinePlayer(profile);
|
||||
}
|
||||
|
||||
var inventory = targetPlayer.getEnderChestInventory();
|
||||
|
||||
var canEdit = Permissions.check(player, getPermissionNode("edit"), 3);
|
||||
|
||||
var map = Map.of(
|
||||
"player", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
var title = module.locale().get("title", map);
|
||||
|
||||
open(player, inventory, title, canEdit, () -> {
|
||||
if(!isOnline) {
|
||||
PlayerUtils.saveOfflinePlayer(targetPlayer);
|
||||
}
|
||||
});
|
||||
|
||||
source.sendSuccess(() -> module.locale().get("opened", map), true);
|
||||
});
|
||||
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
|
||||
private void open(ServerPlayer player, PlayerEnderChestContainer inventory, Component title, boolean canEdit, Runnable onClose) {
|
||||
var container = new SimpleGui(MenuType.GENERIC_9x3, player, false) {
|
||||
@Override
|
||||
public void onClose() {
|
||||
onClose.run();
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < inventory.getContainerSize(); i++) {
|
||||
Slot slot;
|
||||
if (canEdit) {
|
||||
slot = new Slot(inventory, i, 0, 0);
|
||||
} else {
|
||||
slot = new ImmutableSlot(inventory, i, 0, 0);
|
||||
}
|
||||
container.setSlotRedirect(i, slot);
|
||||
}
|
||||
|
||||
container.setTitle(title);
|
||||
|
||||
container.open();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package me.alexdevs.solstice.modules.enderchest.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class EnderChestLocale {
|
||||
public static final Map<String, String> LOCALE = Map.ofEntries(
|
||||
Map.entry("title", "${player}'s Ender Chest"),
|
||||
Map.entry("exempt", "<red>You cannot open this Ender Chest because the player is exempt.</red>"),
|
||||
Map.entry("opened", "<gold>Opened <yellow>${player}</yellow>'s Ender Chest.</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package me.alexdevs.solstice.modules.experiments;
|
||||
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.experiments.commands.FlagsCommand;
|
||||
import me.alexdevs.solstice.modules.experiments.commands.TimeSpanCommand;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ExperimentsModule extends ModuleBase {
|
||||
public static final boolean ENABLED = false;
|
||||
public static final String ID = "experiments";
|
||||
|
||||
public ExperimentsModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
commands.add(new TimeSpanCommand(this));
|
||||
commands.add(new FlagsCommand(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends ModCommand<?>> getCommands() {
|
||||
if (!ENABLED) return List.of();
|
||||
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package me.alexdevs.solstice.modules.experiments.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.command.Flags;
|
||||
import me.alexdevs.solstice.api.command.flags.ArgumentFlag;
|
||||
import me.alexdevs.solstice.api.command.flags.DoubleFlag;
|
||||
import me.alexdevs.solstice.api.command.flags.Flag;
|
||||
import me.alexdevs.solstice.api.command.flags.StringFlag;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.experiments.ExperimentsModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
|
||||
public class FlagsCommand extends ModCommand<ExperimentsModule> {
|
||||
public FlagsCommand(ExperimentsModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("flags");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require(true))
|
||||
.then(Commands.argument("flags", StringArgumentType.greedyString())
|
||||
.executes(context -> {
|
||||
var source = context.getSource();
|
||||
|
||||
var testFlag = Flag.of("test");
|
||||
var stringFlag = new StringFlag("string", List.of('s'));
|
||||
var numberFlag = new DoubleFlag("number", List.of('n'));
|
||||
|
||||
Flags.parse(StringArgumentType.getString(context, "flags"), testFlag, stringFlag, numberFlag);
|
||||
|
||||
for (var flag : List.of(testFlag, stringFlag, numberFlag)) {
|
||||
if (flag.isUsed()) {
|
||||
if (flag.acceptsValue() && flag instanceof ArgumentFlag<?> argFlag) {
|
||||
var value = argFlag.getValue();
|
||||
source.sendSystemMessage(Component.nullToEmpty(String.format("Flag %s: %s", flag.getName(), value)));
|
||||
|
||||
} else {
|
||||
source.sendSystemMessage(Component.nullToEmpty(String.format("Flag %s", flag.getName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package me.alexdevs.solstice.modules.experiments.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.command.TimeSpan;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.experiments.ExperimentsModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class TimeSpanCommand extends ModCommand<ExperimentsModule> {
|
||||
|
||||
public TimeSpanCommand(ExperimentsModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("timespan");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.then(argument("timespan", StringArgumentType.string())
|
||||
.suggests(TimeSpan::suggest)
|
||||
.executes(this::execute));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
var timespan = TimeSpan.getTimeSpan(context, "timespan");
|
||||
context.getSource().sendSuccess(() -> Component.nullToEmpty(String.format("Got %s (%d)", TimeSpan.toShortString(timespan), timespan)), false);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package me.alexdevs.solstice.modules.extinguish;
|
||||
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.extinguish.commands.ExtinguishCommand;
|
||||
|
||||
public class ExtinguishModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "extinguish";
|
||||
|
||||
public ExtinguishModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
commands.add(new ExtinguishCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package me.alexdevs.solstice.modules.extinguish.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.extinguish.ExtinguishModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class ExtinguishCommand extends ModCommand<ExtinguishModule> {
|
||||
public ExtinguishCommand(ExtinguishModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
private static int execute(CommandContext<CommandSourceStack> context, @Nullable Collection<ServerPlayer> players) throws CommandSyntaxException {
|
||||
var source = context.getSource();
|
||||
if (players == null) {
|
||||
extinguish(source, source.getPlayerOrException());
|
||||
return 1;
|
||||
} else {
|
||||
for (ServerPlayer player : players) {
|
||||
extinguish(source, player);
|
||||
}
|
||||
|
||||
return players.size();
|
||||
}
|
||||
}
|
||||
|
||||
private static void extinguish(CommandSourceStack source, ServerPlayer player) {
|
||||
player.clearFire();
|
||||
source.sendSuccess(() -> Component.literal("Extinguished ").append(source.getDisplayName()), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("extinguish", "ex");
|
||||
}
|
||||
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String command) {
|
||||
return literal(command)
|
||||
.requires(require(2))
|
||||
.executes(context -> execute(context, null))
|
||||
.then(argument("players", EntityArgument.players())
|
||||
.executes(context -> execute(context, EntityArgument.getPlayers(context, "players"))));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package me.alexdevs.solstice.modules.feed;
|
||||
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.feed.commands.FeedCommand;
|
||||
|
||||
public class FeedModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "feed";
|
||||
|
||||
public FeedModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
commands.add(new FeedCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package me.alexdevs.solstice.modules.feed.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.feed.FeedModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class FeedCommand extends ModCommand<FeedModule> {
|
||||
private static final int MAX_FOOD_LEVEL = 20;
|
||||
|
||||
public FeedCommand(FeedModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("feed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.executes(context -> execute(context, null))
|
||||
.then(argument("targets", EntityArgument.players())
|
||||
.requires(require("others", 2))
|
||||
.executes(context -> execute(context, EntityArgument.getPlayers(context, "targets"))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, @Nullable Collection<ServerPlayer> targets) throws CommandSyntaxException {
|
||||
if (targets == null) {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
feed(context, player);
|
||||
return 1;
|
||||
} else {
|
||||
for (var target : targets) {
|
||||
feed(context, target);
|
||||
}
|
||||
|
||||
return targets.size();
|
||||
}
|
||||
}
|
||||
|
||||
private void feed(CommandContext<CommandSourceStack> context, ServerPlayer player) {
|
||||
player.getFoodData().setFoodLevel(MAX_FOOD_LEVEL);
|
||||
player.getFoodData().setSaturation(MAX_FOOD_LEVEL);
|
||||
context.getSource().sendSuccess(() -> Component.literal("Fed ").append(player.getDisplayName()), true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package me.alexdevs.solstice.modules.fly;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.fly.commands.FlyCommand;
|
||||
import me.alexdevs.solstice.modules.fly.data.FlyLocale;
|
||||
import me.alexdevs.solstice.modules.fly.data.FlyPlayerData;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
|
||||
public class FlyModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "fly";
|
||||
|
||||
public FlyModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, FlyLocale.MODULE);
|
||||
Solstice.playerData.registerData(ID, FlyPlayerData.class, FlyPlayerData::new);
|
||||
|
||||
commands.add(new FlyCommand(this));
|
||||
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
var player = handler.getPlayer();
|
||||
|
||||
var data = Solstice.playerData.get(player).getData(FlyPlayerData.class);
|
||||
if(data.flightEnabled) {
|
||||
var abilities = player.getAbilities();
|
||||
abilities.mayfly = true;
|
||||
player.onUpdateAbilities();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package me.alexdevs.solstice.modules.fly.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.fly.FlyModule;
|
||||
import me.alexdevs.solstice.modules.fly.data.FlyPlayerData;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class FlyCommand extends ModCommand<FlyModule> {
|
||||
public FlyCommand(FlyModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("fly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(3))
|
||||
.executes(context -> execute(context, null))
|
||||
.then(argument("player", EntityArgument.player())
|
||||
.requires(require("others", 3))
|
||||
.executes(context -> execute(context, EntityArgument.getPlayer(context, "player")))
|
||||
);
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, @Nullable ServerPlayer player) throws CommandSyntaxException {
|
||||
var forOther = player != null;
|
||||
if (player == null) {
|
||||
player = context.getSource().getPlayerOrException();
|
||||
}
|
||||
|
||||
var abilities = player.getAbilities();
|
||||
abilities.mayfly = !abilities.mayfly;
|
||||
player.onUpdateAbilities();
|
||||
|
||||
var data = Solstice.playerData.get(player).getData(FlyPlayerData.class);
|
||||
data.flightEnabled = abilities.mayfly;
|
||||
|
||||
Component text;
|
||||
var sourceContext = PlaceholderContext.of(context.getSource());
|
||||
if (forOther) {
|
||||
var placeholders = Map.of(
|
||||
"player", player.getDisplayName()
|
||||
);
|
||||
|
||||
if (abilities.mayfly) {
|
||||
text = module.locale().get("enabledForOther", sourceContext, placeholders);
|
||||
} else {
|
||||
text = module.locale().get("disabledForOther", sourceContext, placeholders);
|
||||
}
|
||||
} else {
|
||||
if (abilities.mayfly) {
|
||||
text = module.locale().get("enabled", sourceContext);
|
||||
} else {
|
||||
text = module.locale().get("disabled", sourceContext);
|
||||
}
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() -> text, forOther);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package me.alexdevs.solstice.modules.fly.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class FlyLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("enabled", "<green>Flight enabled</green>"),
|
||||
Map.entry("disabled", "<gold>Flight disabled</gold>"),
|
||||
Map.entry("enabledForOther", "<green>Flight enabled for ${player}</green>"),
|
||||
Map.entry("disabledForOther", "<gold>Flight disabled for ${player}</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package me.alexdevs.solstice.modules.fly.data;
|
||||
|
||||
public class FlyPlayerData {
|
||||
public boolean flightEnabled = false;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package me.alexdevs.solstice.modules.god;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.god.commands.GodCommand;
|
||||
import me.alexdevs.solstice.modules.god.data.GodLocale;
|
||||
import me.alexdevs.solstice.modules.god.data.GodPlayerData;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
|
||||
public class GodModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "god";
|
||||
|
||||
public GodModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, GodLocale.MODULE);
|
||||
Solstice.playerData.registerData(ID, GodPlayerData.class, GodPlayerData::new);
|
||||
|
||||
commands.add(new GodCommand(this));
|
||||
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
var player = handler.getPlayer();
|
||||
|
||||
var data = Solstice.playerData.get(player).getData(GodPlayerData.class);
|
||||
if(data.invulnerabilityEnabled) {
|
||||
var abilities = player.getAbilities();
|
||||
abilities.invulnerable = true;
|
||||
player.onUpdateAbilities();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
package me.alexdevs.solstice.modules.god.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.god.GodModule;
|
||||
import me.alexdevs.solstice.modules.god.data.GodPlayerData;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class GodCommand extends ModCommand<GodModule> {
|
||||
public GodCommand(GodModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("god");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(3))
|
||||
.executes(context -> execute(context, null))
|
||||
.then(argument("player", EntityArgument.player())
|
||||
.requires(require("others", 3))
|
||||
.executes(context -> execute(context, EntityArgument.getPlayer(context, "player")))
|
||||
);
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, @Nullable ServerPlayer player) throws CommandSyntaxException {
|
||||
var forOther = player != null;
|
||||
if (player == null) {
|
||||
player = context.getSource().getPlayerOrException();
|
||||
}
|
||||
|
||||
var abilities = player.getAbilities();
|
||||
abilities.invulnerable = !abilities.invulnerable;
|
||||
player.onUpdateAbilities();
|
||||
|
||||
var data = Solstice.playerData.get(player).getData(GodPlayerData.class);
|
||||
data.invulnerabilityEnabled = abilities.invulnerable;
|
||||
|
||||
Component text;
|
||||
var sourceContext = PlaceholderContext.of(context.getSource());
|
||||
if (forOther) {
|
||||
var placeholders = Map.of(
|
||||
"player", player.getDisplayName()
|
||||
);
|
||||
|
||||
if (abilities.invulnerable) {
|
||||
text = module.locale().get("enabledForOther", sourceContext, placeholders);
|
||||
} else {
|
||||
text = module.locale().get("disabledForOther", sourceContext, placeholders);
|
||||
}
|
||||
} else {
|
||||
if (abilities.invulnerable) {
|
||||
text = module.locale().get("enabled", sourceContext);
|
||||
} else {
|
||||
text = module.locale().get("disabled", sourceContext);
|
||||
}
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() -> text, forOther);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package me.alexdevs.solstice.modules.god.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GodLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("enabled", "<green>Invincibility enabled</green>"),
|
||||
Map.entry("disabled", "<gold>Invincibility disabled</gold>"),
|
||||
Map.entry("enabledForOther", "<green>Invincibility enabled for ${player}</green>"),
|
||||
Map.entry("disabledForOther", "<gold>Invincibility disabled for ${player}</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package me.alexdevs.solstice.modules.god.data;
|
||||
|
||||
public class GodPlayerData {
|
||||
public boolean invulnerabilityEnabled = false;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package me.alexdevs.solstice.modules.hat;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.hat.commands.HatCommand;
|
||||
import me.alexdevs.solstice.modules.hat.data.HatConfig;
|
||||
import me.alexdevs.solstice.modules.hat.data.HatLocale;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class HatModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "hat";
|
||||
|
||||
public HatModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, HatConfig.class, HatConfig::new);
|
||||
Solstice.localeManager.registerModule(ID, HatLocale.MODULE);
|
||||
|
||||
commands.add(new HatCommand(this));
|
||||
}
|
||||
|
||||
public HatConfig getConfig() {
|
||||
return Solstice.configManager.getData(HatConfig.class);
|
||||
}
|
||||
|
||||
public List<String> getConfigTags() {
|
||||
return getConfig().filter.stream().filter(s -> s.startsWith("#")).toList();
|
||||
}
|
||||
|
||||
public List<String> getConfigItems() {
|
||||
return getConfig().filter.stream().filter(s -> !s.startsWith("#")).toList();
|
||||
}
|
||||
|
||||
public boolean isInFilter(String key) {
|
||||
if (key.startsWith("#")) {
|
||||
return getConfigTags().contains(key);
|
||||
} else {
|
||||
return getConfigItems().contains(key);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInFilter(Stream<TagKey<Item>> stream) {
|
||||
var tags = getConfigTags().stream().map(t -> t.substring(1)).toList();
|
||||
var iter = stream.iterator();
|
||||
while (iter.hasNext()) {
|
||||
var tag = iter.next();
|
||||
if(tags.contains(tag.location().toString()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package me.alexdevs.solstice.modules.hat.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.hat.HatModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class HatCommand extends ModCommand<HatModule> {
|
||||
public HatCommand(HatModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("hat");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var handStack = player.getMainHandItem();
|
||||
|
||||
if (handStack.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("emptyStack"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var config = module.getConfig();
|
||||
|
||||
var itemId = handStack.getItemHolder().unwrapKey().get().location().toString();
|
||||
var tags = handStack.getTags();
|
||||
if (config.whitelistFilter) {
|
||||
if(!module.isInFilter(itemId) && !module.isInFilter(tags)) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("notAllowed"), false);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(module.isInFilter(itemId) || module.isInFilter(tags)) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("notAllowed"), false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//handStack.streamTags().toList().get(0).id().toString();
|
||||
|
||||
var inventory = player.getInventory();
|
||||
var oldHeadStack = inventory.armor.get(3); // head slot
|
||||
inventory.setItem(inventory.selected, oldHeadStack.copyAndClear());
|
||||
inventory.armor.set(3, handStack.copyAndClear());
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("success"), false);
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package me.alexdevs.solstice.modules.hat.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class HatConfig {
|
||||
|
||||
@Comment("Make the filter setting act as a whitelist instead of a blacklist.")
|
||||
public boolean whitelistFilter = false;
|
||||
|
||||
@Comment("Items & tags to allow/deny. See the 'whitelist-filter' setting to change the behaviour of this list.\nUse '#' as prefix to filter as tag.")
|
||||
public List<String> filter = List.of(
|
||||
"#c:shulker_boxes"
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package me.alexdevs.solstice.modules.hat.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class HatLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("emptyStack", "<red>You are not holding any item!</red>"),
|
||||
Map.entry("success", "<green>Check out your new hat!</green>"),
|
||||
Map.entry("notAllowed", "<gold>You cannot wear this item!</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package me.alexdevs.solstice.modules.heal;
|
||||
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.heal.commands.HealCommand;
|
||||
|
||||
public class HealModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "heal";
|
||||
|
||||
public HealModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
commands.add(new HealCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package me.alexdevs.solstice.modules.heal.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.heal.HealModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class HealCommand extends ModCommand<HealModule> {
|
||||
public HealCommand(HealModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("heal");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.executes(context -> execute(context, null))
|
||||
.then(argument("targets", EntityArgument.entities())
|
||||
.requires(require("others", 2))
|
||||
.executes(context -> execute(context, EntityArgument.getEntities(context, "targets"))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, @Nullable Collection<? extends Entity> targets) throws CommandSyntaxException {
|
||||
if (targets == null) {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
heal(context, player);
|
||||
return 1;
|
||||
} else {
|
||||
var healedCount = 0;
|
||||
for (var target : targets) {
|
||||
if (target instanceof LivingEntity livingEntity) {
|
||||
healedCount++;
|
||||
heal(context, livingEntity);
|
||||
}
|
||||
}
|
||||
|
||||
if (healedCount == 0) {
|
||||
context.getSource().sendFailure(Component.nullToEmpty("There are no living entities in the selector"));
|
||||
}
|
||||
return healedCount;
|
||||
}
|
||||
}
|
||||
|
||||
private void heal(CommandContext<CommandSourceStack> context, LivingEntity entity) {
|
||||
entity.setHealth(entity.getMaxHealth());
|
||||
context.getSource().sendSuccess(() -> Component.literal("Healed ").append(entity.getDisplayName()), true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package me.alexdevs.solstice.modules.helpOp;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.helpOp.commands.HelpOpCommand;
|
||||
import me.alexdevs.solstice.modules.helpOp.data.HelpOpLocale;
|
||||
|
||||
public class HelpOpModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "helpop";
|
||||
|
||||
public HelpOpModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, HelpOpLocale.MODULE);
|
||||
|
||||
commands.add(new HelpOpCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package me.alexdevs.solstice.modules.helpOp.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.locale.Locale;
|
||||
import me.alexdevs.solstice.modules.helpOp.HelpOpModule;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class HelpOpCommand extends ModCommand<HelpOpModule> {
|
||||
private final Locale locale = Solstice.localeManager.getLocale(HelpOpModule.ID);
|
||||
|
||||
public HelpOpCommand(HelpOpModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("helpop", "sos");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.then(argument("message", StringArgumentType.greedyString())
|
||||
.executes(context -> {
|
||||
var source = context.getSource();
|
||||
var sourceContext = PlaceholderContext.of(source);
|
||||
var message = StringArgumentType.getString(context, "message");
|
||||
|
||||
var placeholders = Map.of(
|
||||
"message", Component.nullToEmpty(message)
|
||||
);
|
||||
var requestMessage = locale.get(
|
||||
"helpRequestMessage",
|
||||
sourceContext,
|
||||
placeholders
|
||||
|
||||
);
|
||||
source.getServer().sendSystemMessage(requestMessage);
|
||||
|
||||
source.getServer().getPlayerList().getPlayers().forEach(player -> {
|
||||
if (Permissions.check(player, getPermissionNode("operator"), 1)) {
|
||||
player.sendSystemMessage(requestMessage);
|
||||
}
|
||||
});
|
||||
|
||||
source.sendSuccess(() -> locale.get("helpRequestFeedback", sourceContext, placeholders), false);
|
||||
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package me.alexdevs.solstice.modules.helpOp.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class HelpOpLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("helpRequestMessage", "❗ <gold>[%player:displayname%]</gold> <gray>${message}</gray>"),
|
||||
Map.entry("helpRequestFeedback", "<gold>Help request sent: </gold><gray>${message}</gray>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package me.alexdevs.solstice.modules.home;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.home.commands.*;
|
||||
import me.alexdevs.solstice.modules.home.data.HomeConfig;
|
||||
import me.alexdevs.solstice.modules.home.data.HomeLocale;
|
||||
import me.alexdevs.solstice.modules.home.data.HomePlayerData;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class HomeModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "home";
|
||||
|
||||
public HomeModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, HomeConfig.class, HomeConfig::new);
|
||||
Solstice.playerData.registerData(ID, HomePlayerData.class, HomePlayerData::new);
|
||||
Solstice.localeManager.registerModule(ID, HomeLocale.MODULE);
|
||||
|
||||
commands.add(new HomeCommand(this));
|
||||
commands.add(new SetHomeCommand(this));
|
||||
commands.add(new HomesCommand(this));
|
||||
commands.add(new DeleteHomeCommand(this));
|
||||
commands.add(new HomeOtherCommand(this));
|
||||
}
|
||||
|
||||
public HomePlayerData getData(UUID player) {
|
||||
return Solstice.playerData.get(player).getData(HomePlayerData.class);
|
||||
}
|
||||
|
||||
public HomeConfig getConfig() {
|
||||
return Solstice.configManager.getData(HomeConfig.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
package me.alexdevs.solstice.modules.home.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.home.HomeModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class DeleteHomeCommand extends ModCommand<HomeModule> {
|
||||
public DeleteHomeCommand(HomeModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("delhome");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> execute(context, "home"))
|
||||
.then(argument("name", StringArgumentType.word())
|
||||
.suggests((context, builder) -> {
|
||||
if (!context.getSource().isPlayer())
|
||||
return SharedSuggestionProvider.suggest(new String[]{}, builder);
|
||||
|
||||
var data = module.getData(context.getSource().getPlayer().getUUID());
|
||||
|
||||
return SharedSuggestionProvider.suggest(data.homes.keySet().stream(), builder);
|
||||
})
|
||||
.executes(context -> execute(context, StringArgumentType.getString(context, "name"))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, String name) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var data = module.getData(player.getUUID());
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
var placeholders = Map.of(
|
||||
"home", Component.nullToEmpty(name)
|
||||
);
|
||||
|
||||
if (!data.homes.containsKey(name)) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"homeNotFound",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
data.homes.remove(name);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"homeDeleted",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package me.alexdevs.solstice.modules.home.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.home.HomeModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class HomeCommand extends ModCommand<HomeModule> {
|
||||
public HomeCommand(HomeModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("home");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> execute(context, "home"))
|
||||
.then(argument("name", StringArgumentType.word())
|
||||
.suggests((context, builder) -> {
|
||||
if (!context.getSource().isPlayer())
|
||||
return SharedSuggestionProvider.suggest(new String[]{}, builder);
|
||||
|
||||
var data = module.getData(context.getSource().getPlayer().getUUID());
|
||||
|
||||
return SharedSuggestionProvider.suggest(data.homes.keySet().stream(), builder);
|
||||
})
|
||||
.executes(context -> execute(context, StringArgumentType.getString(context, "name"))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, String name) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var data = module.getData(player.getUUID());
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
var placeholders = Map.of(
|
||||
"home", Component.nullToEmpty(name)
|
||||
);
|
||||
|
||||
if (!data.homes.containsKey(name)) {
|
||||
context.getSource().sendSuccess(() ->
|
||||
module.locale().get(
|
||||
"homeNotFound",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() ->
|
||||
module.locale().get(
|
||||
"teleporting",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
var homePosition = data.homes.get(name);
|
||||
homePosition.teleport(player);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package me.alexdevs.solstice.modules.home.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.home.HomeModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class HomeOtherCommand extends ModCommand<HomeModule> {
|
||||
public HomeOtherCommand(HomeModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("homeother");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require("others", 2))
|
||||
.then(argument("player", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> execute(context, "home"))
|
||||
.then(argument("name", StringArgumentType.word())
|
||||
.executes(context -> execute(context, StringArgumentType.getString(context, "name")))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, String name) throws CommandSyntaxException {
|
||||
var sourcePlayer = context.getSource().getPlayerOrException();
|
||||
var profile = LocalGameProfile.getProfile(context, "player");
|
||||
var playerContext = PlaceholderContext.of(context.getSource().getPlayer());
|
||||
|
||||
|
||||
var data = module.getData(profile.getId());
|
||||
|
||||
var placeholders = Map.of(
|
||||
"home", Component.nullToEmpty(name),
|
||||
"owner", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
|
||||
if (!data.homes.containsKey(name)) {
|
||||
context.getSource().sendSuccess(() ->
|
||||
module.locale().get(
|
||||
"homeNotFound",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() ->
|
||||
module.locale().get(
|
||||
"teleportingOther",
|
||||
playerContext,
|
||||
placeholders
|
||||
), true);
|
||||
|
||||
var homePosition = data.homes.get(name);
|
||||
homePosition.teleport(sourcePlayer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package me.alexdevs.solstice.modules.home.commands;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.home.HomeModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class HomesCommand extends ModCommand<HomeModule> {
|
||||
public HomesCommand(HomeModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("homes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(this::execute)
|
||||
.then(argument("player", StringArgumentType.word())
|
||||
.requires(require("others", 2))
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> executeOthers(context, LocalGameProfile.getProfile(context, "player"))));
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var data = module.getData(player.getUUID());
|
||||
var homeList = data.homes.keySet().stream().toList();
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
if (homeList.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"noHomes",
|
||||
playerContext
|
||||
), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var listText = Component.empty();
|
||||
var comma = module.locale().get("homesComma");
|
||||
for (var i = 0; i < homeList.size(); i++) {
|
||||
if (i > 0) {
|
||||
listText = listText.append(comma);
|
||||
}
|
||||
var placeholders = Map.of(
|
||||
"home", Component.nullToEmpty(homeList.get(i))
|
||||
);
|
||||
|
||||
listText = listText.append(module.locale().get(
|
||||
"homesFormat",
|
||||
playerContext,
|
||||
placeholders
|
||||
));
|
||||
}
|
||||
|
||||
var placeholders = Map.of(
|
||||
"homeList", (Component) listText
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"homeList",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return homeList.size();
|
||||
}
|
||||
|
||||
private int executeOthers(CommandContext<CommandSourceStack> context, GameProfile profile) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
var data = module.getData(profile.getId());
|
||||
var homeList = data.homes.keySet().stream().toList();
|
||||
|
||||
if (homeList.isEmpty()) {
|
||||
var placeholders = Map.of(
|
||||
"owner", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"noHomesOther",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var listText = Component.empty();
|
||||
var comma = module.locale().get("homesComma");
|
||||
for (var i = 0; i < homeList.size(); i++) {
|
||||
if (i > 0) {
|
||||
listText = listText.append(comma);
|
||||
}
|
||||
var placeholders = Map.of(
|
||||
"home", Component.nullToEmpty(homeList.get(i)),
|
||||
"owner", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
|
||||
listText = listText.append(module.locale().get(
|
||||
"homesFormatOther",
|
||||
playerContext,
|
||||
placeholders
|
||||
));
|
||||
}
|
||||
|
||||
var placeholders = Map.of(
|
||||
"homeList", listText,
|
||||
"owner", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"homeListOther",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return homeList.size();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
package me.alexdevs.solstice.modules.home.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.home.HomeModule;
|
||||
import me.alexdevs.solstice.api.text.Components;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class SetHomeCommand extends ModCommand<HomeModule> {
|
||||
public SetHomeCommand(HomeModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("sethome");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> execute(context,
|
||||
"home",
|
||||
false))
|
||||
.then(argument("name", StringArgumentType.word())
|
||||
.executes(context -> execute(context,
|
||||
StringArgumentType.getString(context, "name"),
|
||||
false))
|
||||
.then(literal("force")
|
||||
.executes(context -> execute(context,
|
||||
StringArgumentType.getString(context, "name"),
|
||||
true))));
|
||||
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, String name, boolean forced) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var data = module.getData(player.getUUID());
|
||||
var homes = data.homes;
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
var placeholders = Map.of(
|
||||
"home", Component.nullToEmpty(name),
|
||||
"forceSetButton", Components.button(
|
||||
module.locale().raw("forceSetLabel"),
|
||||
module.locale().raw("forceSetHover"),
|
||||
"/sethome " + name + " force"
|
||||
)
|
||||
);
|
||||
|
||||
var exists = homes.containsKey(name);
|
||||
if (exists && !forced) {
|
||||
var text = module.locale().get(
|
||||
"homeExists",
|
||||
playerContext,
|
||||
placeholders
|
||||
);
|
||||
|
||||
context.getSource().sendSuccess(() -> text, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
homes.remove(name);
|
||||
|
||||
var groups = module.getConfig().homes;
|
||||
var maxHomes = Integer.MIN_VALUE;
|
||||
for(var entry : groups.entrySet()) {
|
||||
var group = entry.getKey();
|
||||
if(Permissions.check(player, "group." + group)) {
|
||||
maxHomes = Math.max(maxHomes, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
var allowUnlimited = Permissions.check(player, getPermissionNode("unlimited"), 3);
|
||||
if (!allowUnlimited && homes.size() >= maxHomes) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"maxHomesReached",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var homePosition = new ServerLocation(player);
|
||||
homes.put(name, homePosition);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"homeSetSuccess",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package me.alexdevs.solstice.modules.home.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ConfigSerializable
|
||||
public class HomeConfig {
|
||||
|
||||
@Comment("The amount of homes a player can set based on their permission group. <group> = <max homes>.\nUse the permission 'solstice.home.unlimited' to bypass this limit.")
|
||||
public Map<String, Integer> homes = Map.of(
|
||||
"default", 5,
|
||||
"vip", 10
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package me.alexdevs.solstice.modules.home.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class HomeLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("teleporting", "<gold>Teleporting to <yellow>${home}</yellow></gold>"),
|
||||
Map.entry("teleportingOther", "<gold>Teleporting to <yellow>${owner}'s ${home}</yellow></gold>"),
|
||||
Map.entry("homeExists", "<gold>You already have set this home.</gold>\n ${forceSetButton}"),
|
||||
Map.entry("homeNotFound", "<red>The home <yellow>${home}</yellow> does not exist!</red>"),
|
||||
Map.entry("maxHomesReached", "<red>You have reached the maximum amount of homes!</red>"),
|
||||
Map.entry("homeSetSuccess", "<gold>New home <yellow>${home}</yellow> set!</gold>"),
|
||||
Map.entry("forceSetLabel", "<yellow>Force set home</yellow>"),
|
||||
Map.entry("forceSetHover", "Click to force setting new home"),
|
||||
Map.entry("homeDeleted", "<gold>Home <yellow>${home}</yellow> deleted!</gold>"),
|
||||
Map.entry("homeList", "<gold>Your homes: ${homeList}</gold>"),
|
||||
Map.entry("homeListOther", "<gold><yellow>${owner}</yellow>'s homes: ${homeList}</gold>"),
|
||||
Map.entry("homesFormat", "<run_cmd:'/home ${home}'><hover:'Click to teleport'><yellow>${home}</yellow></hover></run_cmd>"),
|
||||
Map.entry("homesFormatOther", "<run_cmd:'/homeother ${owner} ${home}'><hover:'Click to teleport'><yellow>${home}</yellow></hover></run_cmd>"),
|
||||
Map.entry("homesComma", "<gold>, </gold>"),
|
||||
Map.entry("noHomes", "<gold>You did not set any home so far.</gold>"),
|
||||
Map.entry("noHomesOther", "<gold><yellow>${owner}</yellow> did not set any home so far.</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package me.alexdevs.solstice.modules.home.data;
|
||||
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ConfigSerializable
|
||||
public class HomePlayerData {
|
||||
public ConcurrentHashMap<String, ServerLocation> homes = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package me.alexdevs.solstice.modules.ignite;
|
||||
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.ignite.commands.IgniteCommand;
|
||||
|
||||
public class IgniteModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "ignite";
|
||||
|
||||
public IgniteModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
commands.add(new IgniteCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package me.alexdevs.solstice.modules.ignite.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.ignite.IgniteModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class IgniteCommand extends ModCommand<IgniteModule> {
|
||||
public static final int defaultTicks = 200; // 10 seconds
|
||||
|
||||
public IgniteCommand(IgniteModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("ignite");
|
||||
}
|
||||
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String command) {
|
||||
return literal(command)
|
||||
.requires(require(2))
|
||||
.executes(context -> execute(context, null, null))
|
||||
.then(argument("players", EntityArgument.players())
|
||||
.executes(context -> execute(context, EntityArgument.getPlayers(context, "players"), null))
|
||||
.then(argument("ticks", IntegerArgumentType.integer(0))
|
||||
.executes(context ->
|
||||
execute(context, EntityArgument.getPlayers(context, "players"), IntegerArgumentType.getInteger(context, "ticks"))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, @Nullable Collection<ServerPlayer> players, @Nullable Integer ticks) throws CommandSyntaxException {
|
||||
var source = context.getSource();
|
||||
if (players == null) {
|
||||
ignite(source, source.getPlayerOrException(), ticks);
|
||||
return 1;
|
||||
} else {
|
||||
for (ServerPlayer player : players) {
|
||||
ignite(source, player, ticks);
|
||||
}
|
||||
|
||||
return players.size();
|
||||
}
|
||||
}
|
||||
|
||||
private void ignite(CommandSourceStack source, ServerPlayer player, @Nullable Integer ticks) {
|
||||
if (ticks == null) {
|
||||
player.setRemainingFireTicks(defaultTicks);
|
||||
source.sendSuccess(() -> Component.literal("Ignited ").append(source.getDisplayName()), true);
|
||||
} else {
|
||||
player.setRemainingFireTicks(ticks);
|
||||
source.sendSuccess(() -> Component.literal("Ignited ").append(source.getDisplayName()).append(Component.nullToEmpty(String.format(" for %d ticks", ticks))), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package me.alexdevs.solstice.modules.ignore;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.ignore.commands.IgnoreCommand;
|
||||
import me.alexdevs.solstice.modules.ignore.commands.IgnoreListCommand;
|
||||
import me.alexdevs.solstice.modules.ignore.data.IgnoreLocale;
|
||||
import me.alexdevs.solstice.modules.ignore.data.IgnorePlayerData;
|
||||
import me.alexdevs.solstice.modules.styling.StylingModule;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import java.util.UUID;
|
||||
|
||||
public class IgnoreModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "ignore";
|
||||
|
||||
public IgnoreModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, IgnoreLocale.MODULE);
|
||||
Solstice.playerData.registerData(ID, IgnorePlayerData.class, IgnorePlayerData::new);
|
||||
|
||||
commands.add(new IgnoreCommand(this));
|
||||
commands.add(new IgnoreListCommand(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return super.isEnabled() && Solstice.modules.getModule(StylingModule.class).isEnabled();
|
||||
}
|
||||
|
||||
public IgnorePlayerData getPlayerData(UUID playerUuid) {
|
||||
return Solstice.playerData.get(playerUuid).getData(IgnorePlayerData.class);
|
||||
}
|
||||
|
||||
public boolean isIgnoring(ServerPlayer player, ServerPlayer target) {
|
||||
return getPlayerData(player.getUUID()).ignoredPlayers.contains(target.getUUID()) && !Permissions.check(target, this.getPermissionNode("exempt"), 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package me.alexdevs.solstice.modules.ignore.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.ignore.IgnoreModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class IgnoreCommand extends ModCommand<IgnoreModule> {
|
||||
public IgnoreCommand(IgnoreModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("ignore");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.then(argument("target", StringArgumentType.word())
|
||||
.suggests((context, builder) -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var playerManager = context.getSource().getServer().getPlayerList();
|
||||
return SharedSuggestionProvider.suggest(Arrays.stream(playerManager.getPlayerNamesArray()).filter(s -> !s.equals(player.getGameProfile().getName())), builder);
|
||||
})
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
|
||||
var targetName = StringArgumentType.getString(context, "target");
|
||||
|
||||
context.getSource().getServer().getProfileCache().getAsync(targetName).thenAcceptAsync(profileOpt -> {
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
if (profileOpt.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("playerNotFound", playerContext), false);
|
||||
return;
|
||||
}
|
||||
|
||||
var profile = profileOpt.get();
|
||||
|
||||
if (profile.getId().equals(player.getGameProfile().getId())) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("targetIsSelf", playerContext), false);
|
||||
return;
|
||||
}
|
||||
|
||||
var playerData = module.getPlayerData(player.getUUID());
|
||||
|
||||
var map = Map.of("targetName", Component.nullToEmpty(profile.getName()));
|
||||
|
||||
if (playerData.ignoredPlayers.contains(profile.getId())) {
|
||||
playerData.ignoredPlayers.remove(profile.getId());
|
||||
context.getSource().sendSuccess(() -> module.locale().get("unblockedPlayer", playerContext, map), false);
|
||||
|
||||
} else {
|
||||
playerData.ignoredPlayers.add(profile.getId());
|
||||
context.getSource().sendSuccess(() -> module.locale().get("blockedPlayer", playerContext, map), false);
|
||||
}
|
||||
});
|
||||
|
||||
return 1;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package me.alexdevs.solstice.modules.ignore.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.ignore.IgnoreModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class IgnoreListCommand extends ModCommand<IgnoreModule> {
|
||||
public IgnoreListCommand(IgnoreModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("ignorelist");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var playerData = module.getPlayerData(player.getUUID());
|
||||
var ignoreList = playerData.ignoredPlayers;
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
|
||||
if (ignoreList.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("ignoreListEmpty",
|
||||
playerContext
|
||||
), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var listText = Component.empty();
|
||||
var comma = module.locale().get("ignoreListComma");
|
||||
for (var i = 0; i < ignoreList.size(); i++) {
|
||||
if (i > 0) {
|
||||
listText = listText.append(comma);
|
||||
}
|
||||
|
||||
String playerName;
|
||||
var gameProfile = context.getSource().getServer().getProfileCache().get(ignoreList.get(i));
|
||||
if (gameProfile.isPresent()) {
|
||||
playerName = gameProfile.get().getName();
|
||||
} else {
|
||||
playerName = ignoreList.get(i).toString();
|
||||
}
|
||||
|
||||
var placeholders = Map.of(
|
||||
"player", Component.nullToEmpty(playerName)
|
||||
);
|
||||
|
||||
listText = listText.append(module.locale().get(
|
||||
"ignoreListFormat",
|
||||
playerContext,
|
||||
placeholders
|
||||
));
|
||||
}
|
||||
|
||||
var placeholders = Map.of(
|
||||
"playerList", (Component) listText
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"ignoreList",
|
||||
playerContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package me.alexdevs.solstice.modules.ignore.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class IgnoreLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("playerNotFound", "<red>Could not find this player</red>"),
|
||||
Map.entry("targetIsSelf", "<red>You cannot ignore yourself.</red>"),
|
||||
Map.entry("blockedPlayer", "<yellow>${targetName}</yellow> <gold>is now ignored.</gold>"),
|
||||
Map.entry("unblockedPlayer", "<yellow>${targetName}</yellow> <green>is no longer ignored.</green>"),
|
||||
Map.entry("ignoreList", "<gold>Ignored players: ${playerList}</gold>"),
|
||||
Map.entry("ignoreListFormat", "<run_cmd:'/ignore ${player}'><hover:'Click to unblock'><yellow>${player}</yellow></hover></run_cmd>"),
|
||||
Map.entry("ignoreListComma", "<gold>, </gold>"),
|
||||
Map.entry("ignoreListEmpty", "<gold>You are not ignoring anyone at the moment.</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package me.alexdevs.solstice.modules.ignore.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
public class IgnorePlayerData {
|
||||
public ArrayList<UUID> ignoredPlayers = new ArrayList<>();
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package me.alexdevs.solstice.modules.info;
|
||||
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.Paths;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import me.alexdevs.solstice.modules.info.commands.InfoCommand;
|
||||
import me.alexdevs.solstice.modules.info.commands.MotdCommand;
|
||||
import me.alexdevs.solstice.modules.info.commands.RulesCommand;
|
||||
import me.alexdevs.solstice.modules.info.data.InfoConfig;
|
||||
import me.alexdevs.solstice.modules.info.data.InfoLocale;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
public class InfoModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "info";
|
||||
|
||||
private static final String[] startingPages = new String[]{
|
||||
"motd.txt",
|
||||
"rules.txt",
|
||||
"formatting.txt"
|
||||
};
|
||||
public final String nameFilterRegex = "[^a-z0-9-]";
|
||||
private final Path infoDir;
|
||||
|
||||
public InfoModule() {
|
||||
super(ID);
|
||||
infoDir = Paths.configDirectory.resolve("info");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, InfoConfig.class, InfoConfig::new);
|
||||
Solstice.localeManager.registerModule(ID, InfoLocale.MODULE);
|
||||
|
||||
commands.add(new InfoCommand(this));
|
||||
commands.add(new MotdCommand(this));
|
||||
commands.add(new RulesCommand(this));
|
||||
|
||||
if (!infoDir.toFile().isDirectory()) {
|
||||
if (!infoDir.toFile().mkdirs()) {
|
||||
Solstice.LOGGER.error("Couldn't create info directory");
|
||||
return;
|
||||
}
|
||||
|
||||
var classLoader = Solstice.class.getClassLoader();
|
||||
var infoDirBase = "assets/" + Solstice.MOD_ID + "/info/";
|
||||
for (var name : startingPages) {
|
||||
var outputPath = infoDir.resolve(name);
|
||||
try (var inputStream = classLoader.getResourceAsStream(infoDirBase + name)) {
|
||||
if (inputStream == null) {
|
||||
Solstice.LOGGER.warn("Missing {} info file in resources, skipping", name);
|
||||
continue;
|
||||
}
|
||||
var content = inputStream.readAllBytes();
|
||||
Files.write(outputPath, content);
|
||||
} catch (IOException e) {
|
||||
Solstice.LOGGER.error("Could not read info file {} from resources", name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
if (getConfig().enableMotd) {
|
||||
if (!exists("motd")) {
|
||||
Solstice.LOGGER.warn("Could not send MOTD because info/motd.txt does not exist!");
|
||||
return;
|
||||
}
|
||||
Solstice.nextTick(() -> {
|
||||
var motd = buildMotd(PlaceholderContext.of(handler.getPlayer()));
|
||||
handler.getPlayer().sendSystemMessage(motd);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public InfoConfig getConfig() {
|
||||
return Solstice.configManager.getData(InfoConfig.class);
|
||||
}
|
||||
|
||||
public Component buildMotd(PlaceholderContext context) {
|
||||
return getPage("motd", context);
|
||||
}
|
||||
|
||||
private String sanitize(String name) {
|
||||
return name.toLowerCase().replaceAll(nameFilterRegex, "");
|
||||
}
|
||||
|
||||
public Collection<String> enumerate() {
|
||||
return Arrays.stream(Objects.requireNonNull(infoDir.toFile().listFiles()))
|
||||
.map(f -> f.getName().replace(".txt", "")).toList();
|
||||
}
|
||||
|
||||
public boolean exists(String name) {
|
||||
name = sanitize(name);
|
||||
var infoFile = infoDir.resolve(name + ".txt");
|
||||
return infoFile.toFile().exists();
|
||||
}
|
||||
|
||||
public Component getPage(String name, @Nullable PlaceholderContext context) {
|
||||
name = sanitize(name);
|
||||
if (!exists(name)) {
|
||||
return locale().get("pageNotFound");
|
||||
}
|
||||
|
||||
var infoFile = infoDir.resolve(name + ".txt");
|
||||
|
||||
try {
|
||||
// Use readAllLines instead readString to avoid \r chars; looking at you, Windows.
|
||||
var lines = Files.readAllLines(infoFile, StandardCharsets.UTF_8);
|
||||
StringBuilder content = new StringBuilder();
|
||||
for (var line : lines) {
|
||||
content.append(line).append("\n");
|
||||
}
|
||||
var output = content.toString().trim();
|
||||
if (context != null)
|
||||
return Format.parse(output, context);
|
||||
else
|
||||
return Component.nullToEmpty(output);
|
||||
} catch (IOException e) {
|
||||
Solstice.LOGGER.error("Could not read info file", e);
|
||||
return locale().get("pageError");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
package me.alexdevs.solstice.modules.info.commands;
|
||||
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.module.Utils;
|
||||
import me.alexdevs.solstice.modules.info.InfoModule;
|
||||
import net.minecraft.commands.CommandBuildContext;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class InfoCommand extends ModCommand<InfoModule> {
|
||||
public InfoCommand(InfoModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext commandRegistry, Commands.CommandSelection environment) {
|
||||
// WorldEdit's /info -> /tool info
|
||||
Utils.removeCommands(dispatcher, "info");
|
||||
super.register(dispatcher, commandRegistry, environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("info", "pages");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(true))
|
||||
.executes(context -> {
|
||||
|
||||
var source = context.getSource();
|
||||
var pageList = module.enumerate();
|
||||
var sourceContext = PlaceholderContext.of(source);
|
||||
|
||||
if (pageList.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"noPages",
|
||||
sourceContext
|
||||
), false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
var listText = Component.empty();
|
||||
var comma = module.locale().get("pagesComma");
|
||||
var list = pageList.stream().toList();
|
||||
for (var i = 0; i < list.size(); i++) {
|
||||
if (i > 0) {
|
||||
listText = listText.append(comma);
|
||||
}
|
||||
var placeholders = Map.of(
|
||||
"page", Component.nullToEmpty(list.get(i))
|
||||
);
|
||||
|
||||
listText = listText.append(module.locale().get(
|
||||
"pagesFormat",
|
||||
sourceContext,
|
||||
placeholders
|
||||
));
|
||||
}
|
||||
|
||||
var placeholders = Map.of(
|
||||
"pageList", (Component) listText
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get(
|
||||
"pageList",
|
||||
sourceContext,
|
||||
placeholders
|
||||
), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
.then(argument("page", StringArgumentType.word())
|
||||
.suggests((context, builder) -> SharedSuggestionProvider.suggest(module.enumerate(), builder))
|
||||
.executes(context -> {
|
||||
var sourceContext = PlaceholderContext.of(context.getSource());
|
||||
var page = module.getPage(StringArgumentType.getString(context, "page"), sourceContext);
|
||||
context.getSource().sendSuccess(() -> page, false);
|
||||
return 1;
|
||||
}));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package me.alexdevs.solstice.modules.info.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.info.InfoModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class MotdCommand extends ModCommand<InfoModule> {
|
||||
public MotdCommand(InfoModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("motd");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require("motd", true))
|
||||
.executes(context -> {
|
||||
var sourceContext = PlaceholderContext.of(context.getSource());
|
||||
|
||||
context.getSource().sendSystemMessage(module.buildMotd(sourceContext));
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package me.alexdevs.solstice.modules.info.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.info.InfoModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class RulesCommand extends ModCommand<InfoModule> {
|
||||
public RulesCommand(InfoModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("rules");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require("rules", true))
|
||||
.executes(context -> {
|
||||
var sourceContext = PlaceholderContext.of(context.getSource());
|
||||
var rules = module.getPage("rules", sourceContext);
|
||||
context.getSource().sendSuccess(() -> rules, false);
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package me.alexdevs.solstice.modules.info.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
@ConfigSerializable
|
||||
public class InfoConfig {
|
||||
@Comment("Send the 'Message Of The Day' to the player when joining the server. Content is in the 'config/solstice/info/motd.txt' file.")
|
||||
public boolean enableMotd = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package me.alexdevs.solstice.modules.info.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class InfoLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("pageNotFound", "<red>This page does not exist!</red>"),
|
||||
Map.entry("pageError", "<red>There was an error opening the info page.</red>"),
|
||||
Map.entry("pageList", "<gold>Available pages: ${pageList}</gold>"),
|
||||
Map.entry("pagesFormat", "<run_cmd:'/info ${page}'><hover:'Click to read'><yellow>${page}</yellow></hover></run_cmd>"),
|
||||
Map.entry("pagesComma", "<gold>, </gold>"),
|
||||
Map.entry("noPages ", "<gold>There are no pages so far.</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package me.alexdevs.solstice.modules.inventorySee;
|
||||
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ImmutableSlot extends Slot {
|
||||
|
||||
public ImmutableSlot(Container inventory, int index, int x, int y) {
|
||||
super(inventory, index, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPickup(Player playerEntity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack stack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowModification(Player player) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package me.alexdevs.solstice.modules.inventorySee;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.inventorySee.commands.InventorySeeCommand;
|
||||
import me.alexdevs.solstice.modules.inventorySee.data.InventorySeeLocale;
|
||||
|
||||
public class InventorySeeModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "inventorysee";
|
||||
|
||||
public InventorySeeModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, InventorySeeLocale.MODULE);
|
||||
|
||||
commands.add(new InventorySeeCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
package me.alexdevs.solstice.modules.inventorySee.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import dev.emi.trinkets.api.TrinketsApi;
|
||||
import eu.pb4.sgui.api.gui.SimpleGui;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.utils.PlayerUtils;
|
||||
import me.alexdevs.solstice.integrations.TrinketsIntegration;
|
||||
import me.alexdevs.solstice.modules.inventorySee.ImmutableSlot;
|
||||
import me.alexdevs.solstice.modules.inventorySee.InventorySeeModule;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.ChestMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.minecraft.commands.Commands.argument;
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
public class InventorySeeCommand extends ModCommand<InventorySeeModule> {
|
||||
public InventorySeeCommand(InventorySeeModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("invsee", "inventorysee");
|
||||
}
|
||||
|
||||
private static final LinkedHashMap<Integer, MenuType<ChestMenu>> invSizes = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
invSizes.put(9, MenuType.GENERIC_9x1);
|
||||
invSizes.put(18, MenuType.GENERIC_9x2);
|
||||
invSizes.put(27, MenuType.GENERIC_9x3);
|
||||
invSizes.put(36, MenuType.GENERIC_9x4);
|
||||
invSizes.put(45, MenuType.GENERIC_9x5);
|
||||
invSizes.put(54, MenuType.GENERIC_9x6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require(2))
|
||||
.then(argument("player", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> {
|
||||
var source = context.getSource();
|
||||
var player = source.getPlayerOrException();
|
||||
var targetProfile = LocalGameProfile.getProfile(context, "player");
|
||||
var targetOnline = PlayerUtils.isOnline(targetProfile.getId());
|
||||
|
||||
if (!targetOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) {
|
||||
source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ServerPlayer target;
|
||||
if (targetOnline) {
|
||||
target = context.getSource().getServer().getPlayerList().getPlayer(targetProfile.getId());
|
||||
if (Permissions.check(target, getPermissionNode("exempt"), 3)) {
|
||||
source.sendSuccess(() -> module.locale().get("exempt"), false);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
target = PlayerUtils.loadOfflinePlayer(targetProfile);
|
||||
if (Permissions.check(targetProfile, getPermissionNode("exempt"), 3, source.getServer()).getNow(false)) {
|
||||
source.sendSuccess(() -> module.locale().get("exempt"), false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
var canEdit = Permissions.check(player, getPermissionNode("edit"), 3);
|
||||
|
||||
var targetInventory = target.getInventory();
|
||||
|
||||
var container = new SimpleGui(MenuType.GENERIC_9x5, player, false) {
|
||||
@Override
|
||||
public void onClose() {
|
||||
if (!targetOnline) {
|
||||
PlayerUtils.saveOfflinePlayer(target);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < targetInventory.getContainerSize(); i++) {
|
||||
Slot slot;
|
||||
if (canEdit) {
|
||||
slot = new Slot(targetInventory, i, 0, 0);
|
||||
} else {
|
||||
slot = new ImmutableSlot(targetInventory, i, 0, 0);
|
||||
}
|
||||
container.setSlotRedirect(i, slot);
|
||||
}
|
||||
|
||||
var barrier = new ItemStack(Items.BLACK_STAINED_GLASS_PANE);
|
||||
barrier.set(DataComponents.CUSTOM_NAME, Component.literal(""));
|
||||
for (var i = targetInventory.getContainerSize(); i < container.getSize(); i++) {
|
||||
container.setSlot(i, barrier);
|
||||
}
|
||||
|
||||
container.setTitle(target.getName());
|
||||
|
||||
container.open();
|
||||
|
||||
var map = Map.of(
|
||||
"user", Component.nullToEmpty(target.getGameProfile().getName())
|
||||
);
|
||||
source.sendSuccess(() -> module.locale().get("openedInventory", map), true);
|
||||
|
||||
return 1;
|
||||
})
|
||||
.then(literal("trinkets")
|
||||
.executes(context -> {
|
||||
var source = context.getSource();
|
||||
var player = source.getPlayerOrException();
|
||||
var targetProfile = LocalGameProfile.getProfile(context, "player");
|
||||
var targetOnline = PlayerUtils.isOnline(targetProfile.getId());
|
||||
|
||||
if (!targetOnline && !Permissions.check(player, getPermissionNode("offline"), 3)) {
|
||||
source.sendSuccess(() -> module.locale().get("offlineNotAllowed"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ServerPlayer target;
|
||||
if (targetOnline) {
|
||||
target = context.getSource().getServer().getPlayerList().getPlayer(targetProfile.getId());
|
||||
if (Permissions.check(target, getPermissionNode("exempt"), 3)) {
|
||||
source.sendSuccess(() -> module.locale().get("exempt"), false);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
target = PlayerUtils.loadOfflinePlayer(targetProfile);
|
||||
if (Permissions.check(targetProfile, getPermissionNode("exempt"), 3, source.getServer()).getNow(false)) {
|
||||
source.sendSuccess(() -> module.locale().get("exempt"), false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!TrinketsIntegration.isAvailable()) {
|
||||
source.sendSuccess(() -> module.locale().get("trinketsNotInstalled"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var canEdit = Permissions.check(player, getPermissionNode("edit"), 3);
|
||||
|
||||
var trinkets = TrinketsApi.getTrinketComponent(target).orElse(null);
|
||||
var slots = new ArrayList<Slot>();
|
||||
for (var group : trinkets.getInventory().values()) {
|
||||
for (var inventory : group.values()) {
|
||||
for (var i = 0; i < inventory.getContainerSize(); i++) {
|
||||
Slot slot;
|
||||
if (canEdit) {
|
||||
slot = new Slot(inventory, i, 0, 0);
|
||||
} else {
|
||||
slot = new ImmutableSlot(inventory, i, 0, 0);
|
||||
}
|
||||
slots.add(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var size = slots.size();
|
||||
MenuType<ChestMenu> handlerType = null;
|
||||
for (var entry : invSizes.entrySet()) {
|
||||
handlerType = entry.getValue();
|
||||
if (size <= entry.getKey()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var container = new SimpleGui(handlerType, player, false) {
|
||||
@Override
|
||||
public void onClose() {
|
||||
if (!targetOnline) {
|
||||
PlayerUtils.saveOfflinePlayer(target);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < slots.size(); i++) {
|
||||
var slot = slots.get(i);
|
||||
container.setSlotRedirect(i, slot);
|
||||
}
|
||||
|
||||
var barrier = new ItemStack(Items.BLACK_STAINED_GLASS_PANE);
|
||||
barrier.set(DataComponents.CUSTOM_NAME, Component.literal(""));
|
||||
for (var i = size; i < container.getSize(); i++) {
|
||||
container.setSlot(i, barrier);
|
||||
}
|
||||
|
||||
container.setTitle(target.getName());
|
||||
container.open();
|
||||
|
||||
var map = Map.of(
|
||||
"user", Component.nullToEmpty(target.getGameProfile().getName())
|
||||
);
|
||||
source.sendSuccess(() -> module.locale().get("openedTrinkets", map), true);
|
||||
|
||||
return 1;
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package me.alexdevs.solstice.modules.inventorySee.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class InventorySeeLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("exempt", "<gold>You cannot open this inventory because the user is exempt.</gold>"),
|
||||
Map.entry("openedInventory", "<gold>Opened <yellow>${user}</yellow>'s inventory.</gold>"),
|
||||
Map.entry("openedTrinkets", "<gold>Opened <yellow>${user}</yellow>'s trinkets inventory.</gold>"),
|
||||
Map.entry("trinketsNotInstalled", "<gold>Trinkets not available because the mod is missing.</gold>"),
|
||||
Map.entry("playerNotFound", "<gold>Player not found!</gold>"),
|
||||
Map.entry("offlineNotAllowed", "<gold>You cannot open offline player inventories.</gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package me.alexdevs.solstice.modules.item;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.item.commands.ItemLoreCommand;
|
||||
import me.alexdevs.solstice.modules.item.commands.ItemNameCommand;
|
||||
import me.alexdevs.solstice.modules.item.commands.MoreCommand;
|
||||
import me.alexdevs.solstice.modules.item.commands.RepairCommand;
|
||||
import me.alexdevs.solstice.modules.item.data.ItemLocale;
|
||||
|
||||
public class ItemModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "item";
|
||||
public ItemModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.localeManager.registerModule(ID, ItemLocale.MODULE);
|
||||
|
||||
commands.add(new ItemLoreCommand(this));
|
||||
commands.add(new ItemNameCommand(this));
|
||||
commands.add(new RepairCommand(this));
|
||||
commands.add(new MoreCommand(this));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package me.alexdevs.solstice.modules.item.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import me.alexdevs.solstice.modules.item.ItemModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.StringTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.component.ItemLore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ItemLoreCommand extends ModCommand<ItemModule> {
|
||||
public ItemLoreCommand(ItemModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("lore", "itemlore");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require("lore", 2))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var item = player.getMainHandItem();
|
||||
|
||||
if (item.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noItem"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
item.remove(DataComponents.LORE);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("loreCleared"), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
.then(Commands.argument("lore", StringArgumentType.greedyString())
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var item = player.getMainHandItem();
|
||||
var itemLore = StringArgumentType.getString(context, "lore");
|
||||
|
||||
if (item.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noItem"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
var list = new ArrayList<Component>();
|
||||
for(var line : itemLore.split("\\\\n")) {
|
||||
list.add(Format.parse(line, playerContext));
|
||||
}
|
||||
|
||||
item.set(DataComponents.LORE, new ItemLore(list));
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("loreSet"), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package me.alexdevs.solstice.modules.item.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.api.text.Format;
|
||||
import me.alexdevs.solstice.modules.item.ItemModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemNameCommand extends ModCommand<ItemModule> {
|
||||
public ItemNameCommand(ItemModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("itemname");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require("name", 2))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var item = player.getMainHandItem();
|
||||
|
||||
if(item.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noItem"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
item.remove(DataComponents.CUSTOM_NAME);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("nameCleared"), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
.then(Commands.argument("name", StringArgumentType.greedyString())
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var item = player.getMainHandItem();
|
||||
var itemName = StringArgumentType.getString(context, "name");
|
||||
|
||||
if(item.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noItem"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var playerContext = PlaceholderContext.of(player);
|
||||
item.set(DataComponents.CUSTOM_NAME, Format.parse(itemName, playerContext));
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("nameSet"), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package me.alexdevs.solstice.modules.item.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.item.ItemModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import java.util.List;
|
||||
|
||||
public class MoreCommand extends ModCommand<ItemModule> {
|
||||
public MoreCommand(ItemModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("more", "stack");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require("more", 2))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var item = player.getMainHandItem();
|
||||
|
||||
if(item.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noItem"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
item.setCount(item.getMaxStackSize());
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("stackRefilled"), false);
|
||||
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package me.alexdevs.solstice.modules.item.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.item.ItemModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraft.commands.Commands.literal;
|
||||
|
||||
|
||||
public class RepairCommand extends ModCommand<ItemModule> {
|
||||
public RepairCommand(ItemModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("repair", "repairitem");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return literal(name)
|
||||
.requires(require("repair", 2))
|
||||
.executes(context -> {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
|
||||
var item = player.getMainHandItem();
|
||||
|
||||
if(item.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noItem"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!item.isDamageableItem()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("notRepairable"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(item.isDamaged()) {
|
||||
// Removes the NBT tag altogether instead of just setting it to 0
|
||||
item.remove(DataComponents.DAMAGE);
|
||||
context.getSource().sendSuccess(() -> module.locale().get("repaired"), false);
|
||||
return 1;
|
||||
} else {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("alreadyRepaired"), false);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package me.alexdevs.solstice.modules.item.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("noItem", "<gold>You are not holding any item!</gold>"),
|
||||
Map.entry("nameSet", "<green>Successfully set the new item name!</green>"),
|
||||
Map.entry("nameCleared", "<gold>Item name cleared!</gold>"),
|
||||
Map.entry("loreSet", "<green>Successfully set the new item lore!</green>"),
|
||||
Map.entry("loreCleared", "<gold>Item lore cleared!</gold>"),
|
||||
Map.entry("repaired", "<green>Item repaired!</green>"),
|
||||
Map.entry("alreadyRepaired", "<gold>This item is already repaired!</gold>"),
|
||||
Map.entry("notRepairable", "<gold>This item is not repairable!</gold>"),
|
||||
Map.entry("stackRefilled", "<green>Item stack refilled!</green>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
package me.alexdevs.solstice.modules.jail;
|
||||
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.api.command.TimeSpan;
|
||||
import me.alexdevs.solstice.api.events.CommandEvents;
|
||||
import me.alexdevs.solstice.api.module.ModuleBase;
|
||||
import me.alexdevs.solstice.modules.jail.commands.CheckJailCommand;
|
||||
import me.alexdevs.solstice.modules.jail.commands.JailCommand;
|
||||
import me.alexdevs.solstice.modules.jail.commands.JailsCommand;
|
||||
import me.alexdevs.solstice.modules.jail.commands.UnjailCommand;
|
||||
import me.alexdevs.solstice.modules.jail.data.JailConfig;
|
||||
import me.alexdevs.solstice.modules.jail.data.JailLocale;
|
||||
import me.alexdevs.solstice.modules.jail.data.JailPlayerData;
|
||||
import me.alexdevs.solstice.modules.jail.data.JailServerData;
|
||||
import me.alexdevs.solstice.modules.spawn.SpawnModule;
|
||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.event.player.*;
|
||||
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class JailModule extends ModuleBase.Toggleable {
|
||||
public static final String ID = "jail";
|
||||
|
||||
public JailModule() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Solstice.configManager.registerData(ID, JailConfig.class, JailConfig::new);
|
||||
Solstice.localeManager.registerModule(ID, JailLocale.MODULE);
|
||||
Solstice.playerData.registerData(ID, JailPlayerData.class, JailPlayerData::new);
|
||||
Solstice.serverData.registerData(ID, JailServerData.class, JailServerData::new);
|
||||
|
||||
commands.add(new JailsCommand(this));
|
||||
commands.add(new JailCommand(this));
|
||||
commands.add(new UnjailCommand(this));
|
||||
commands.add(new CheckJailCommand(this));
|
||||
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||
Solstice.nextTick(() -> {
|
||||
var data = getPlayer(handler.getPlayer().getUUID());
|
||||
if (data.jailed) {
|
||||
sendToJail(handler.getPlayer());
|
||||
} else if (data.teleportToPreviousLocation) {
|
||||
unjailPlayer(handler.getPlayer().getUUID());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, player, alive) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
sendToJail(player);
|
||||
}
|
||||
});
|
||||
|
||||
ServerLifecycleEvents.SERVER_STARTED.register((server) -> {
|
||||
Solstice.scheduler.scheduleAtFixedRate(this::checkJailedPlayers, 0, 1, TimeUnit.SECONDS);
|
||||
});
|
||||
|
||||
CommandEvents.ALLOW_COMMAND.register((source, command) -> {
|
||||
if (!source.isPlayer())
|
||||
return true;
|
||||
|
||||
if (isPlayerJailed(source.getPlayer().getUUID())) {
|
||||
var config = getConfig();
|
||||
var cmd = command.split(" ")[0];
|
||||
var canRun = config.allowedCommands.contains(cmd);
|
||||
if (!canRun) {
|
||||
source.sendSuccess(() -> locale().get("cannotRunCommands"), false);
|
||||
}
|
||||
return canRun;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
AttackBlockCallback.EVENT.register((player, world, hand, blockPos, direction) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
player.sendSystemMessage(locale().get("cannotBreakBlocks"));
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
AttackEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
player.sendSystemMessage(locale().get("cannotAttackEntities"));
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
PlayerBlockBreakEvents.BEFORE.register((world, player, blockPos, blockState, blockEntity) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
player.sendSystemMessage(locale().get("cannotBreakBlocks"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
UseBlockCallback.EVENT.register((player, world, hand, blockHitResult) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
player.sendSystemMessage(locale().get("cannotUseBlocks"));
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
UseEntityCallback.EVENT.register((player, world, hand, entity, entityHitResult) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
player.sendSystemMessage(locale().get("cannotUseEntities"));
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
});
|
||||
|
||||
UseItemCallback.EVENT.register((player, world, hand) -> {
|
||||
var stack = player.getItemInHand(hand);
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
player.sendSystemMessage(locale().get("cannotUseItems"));
|
||||
return InteractionResultHolder.fail(stack);
|
||||
}
|
||||
return InteractionResultHolder.pass(stack);
|
||||
});
|
||||
|
||||
ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((signedMessage, player, parameters) -> {
|
||||
if (isPlayerJailed(player.getUUID())) {
|
||||
var config = getConfig();
|
||||
if(config.mute) {
|
||||
player.sendSystemMessage(locale().get("cannotSpeak"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void checkJailedPlayers() {
|
||||
// run on server thread
|
||||
Solstice.nextTick(() -> {
|
||||
var players = Solstice.server.getPlayerList().getPlayers();
|
||||
for (var player : players) {
|
||||
var data = getPlayer(player.getUUID());
|
||||
if (isPlayerJailed(player.getUUID()) && data.jailTime > 0) {
|
||||
if (data.jailedOn != null && data.jailedOn.getTime() + (data.jailTime * 1000L) < System.currentTimeMillis()) {
|
||||
unjailPlayer(player.getUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public JailConfig getConfig() {
|
||||
return Solstice.configManager.getData(JailConfig.class);
|
||||
}
|
||||
|
||||
public Map<String, ServerLocation> getJails() {
|
||||
return Solstice.serverData.getData(JailServerData.class).jails;
|
||||
}
|
||||
|
||||
public JailPlayerData getPlayer(UUID uuid) {
|
||||
return Solstice.playerData.get(uuid).getData(JailPlayerData.class);
|
||||
}
|
||||
|
||||
public boolean isPlayerJailed(UUID uuid) {
|
||||
return getPlayer(uuid).jailed;
|
||||
}
|
||||
|
||||
public void sendToJail(ServerPlayer player) {
|
||||
Solstice.nextTick(() -> {
|
||||
var data = getPlayer(player.getUUID());
|
||||
var jails = getJails();
|
||||
var jail = jails.get(data.jailName);
|
||||
if (jail != null) {
|
||||
jail.teleport(player);
|
||||
|
||||
var map = Map.of(
|
||||
"player", player.getName(),
|
||||
"jail", Component.nullToEmpty(data.jailName),
|
||||
"duration", Component.nullToEmpty(TimeSpan.toLongString(data.jailTime)),
|
||||
"reason", Component.nullToEmpty(data.jailReason)
|
||||
);
|
||||
|
||||
Component text;
|
||||
if (data.jailTime > 0) {
|
||||
if (data.jailReason != null) {
|
||||
text = locale().get("playerJailedForWithReason", map);
|
||||
} else {
|
||||
text = locale().get("playerJailedFor", map);
|
||||
}
|
||||
} else {
|
||||
text = locale().get("playerJailed", map);
|
||||
}
|
||||
player.displayClientMessage(text, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void unjailPlayer(UUID uuid) {
|
||||
var data = getPlayer(uuid);
|
||||
data.jailed = false;
|
||||
data.teleportToPreviousLocation = true;
|
||||
|
||||
var player = Solstice.server.getPlayerList().getPlayer(uuid);
|
||||
if (player != null) {
|
||||
data.teleportToPreviousLocation = false;
|
||||
|
||||
player.sendSystemMessage(locale().get("playerUnjailed"));
|
||||
|
||||
if (data.previousLocation != null) {
|
||||
data.previousLocation.teleport(player);
|
||||
} else {
|
||||
var spawnModule = Solstice.modules.getModule(SpawnModule.class);
|
||||
spawnModule.getGlobalSpawnPosition().teleport(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package me.alexdevs.solstice.modules.jail.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.command.TimeSpan;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.core.coreModule.data.CoreConfig;
|
||||
import me.alexdevs.solstice.modules.jail.JailModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class CheckJailCommand extends ModCommand<JailModule> {
|
||||
|
||||
public CheckJailCommand(JailModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("checkjail");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require(2))
|
||||
.then(Commands.argument("user", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> {
|
||||
var user = LocalGameProfile.getProfile(context, "user");
|
||||
var data = module.getPlayer(user.getId());
|
||||
|
||||
if (!data.jailed) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("notJailed"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
String operator;
|
||||
if (new UUID(0, 0).equals(data.jailedBy)) {
|
||||
operator = "Server";
|
||||
} else {
|
||||
var opProfile = context.getSource().getServer().getProfileCache().get(data.jailedBy);
|
||||
if (opProfile.isPresent()) {
|
||||
operator = opProfile.get().getName();
|
||||
} else {
|
||||
operator = data.jailedBy != null ? data.jailedBy.toString() : "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
String reason;
|
||||
if (data.jailReason != null) {
|
||||
reason = data.jailReason;
|
||||
} else {
|
||||
reason = module.locale().raw("infoJailReasonEmpty");
|
||||
}
|
||||
|
||||
String duration;
|
||||
if (data.jailTime == 0) {
|
||||
duration = module.locale().raw("infoJailedForEmpty");
|
||||
} else {
|
||||
duration = TimeSpan.toLongString(data.jailTime);
|
||||
}
|
||||
|
||||
var coreConfig = Solstice.configManager.getData(CoreConfig.class);
|
||||
var df = new SimpleDateFormat(coreConfig.dateTimeFormat);
|
||||
|
||||
var map = Map.of(
|
||||
"player", Component.nullToEmpty(user.getName()),
|
||||
"jail", Component.nullToEmpty(data.jailName),
|
||||
"operator", Component.nullToEmpty(operator),
|
||||
"reason", Component.nullToEmpty(reason),
|
||||
"duration", Component.nullToEmpty(duration),
|
||||
"date", Component.nullToEmpty(df.format(data.jailedOn))
|
||||
|
||||
);
|
||||
|
||||
var text = Component.empty();
|
||||
text.append(module.locale().get("infoHeader", map));
|
||||
text.append("\n");
|
||||
text.append(module.locale().get("infoJailedAt", map));
|
||||
text.append("\n");
|
||||
text.append(module.locale().get("infoJailedBy", map));
|
||||
text.append("\n");
|
||||
text.append(module.locale().get("infoJailReason", map));
|
||||
text.append("\n");
|
||||
text.append(module.locale().get("infoJailedFor", map));
|
||||
text.append("\n");
|
||||
text.append(module.locale().get("infoJailedOn", map));
|
||||
|
||||
context.getSource().sendSuccess(() -> text, false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
package me.alexdevs.solstice.modules.jail.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import me.alexdevs.solstice.Solstice;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.command.TimeSpan;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.core.coreModule.data.CorePlayerData;
|
||||
import me.alexdevs.solstice.modules.jail.JailModule;
|
||||
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class JailCommand extends ModCommand<JailModule> {
|
||||
public JailCommand(JailModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("jail");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require("jail", 2))
|
||||
.then(Commands.argument("user", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.then(Commands.argument("jail", StringArgumentType.word())
|
||||
.suggests(this::suggestJails)
|
||||
.executes(context -> execute(context, 0, null))
|
||||
.then(Commands.argument("duration", TimeSpan.timeSpan())
|
||||
.suggests(TimeSpan::suggest)
|
||||
.executes(context -> execute(context, TimeSpan.getTimeSpan(context, "duration"), null))
|
||||
.then(Commands.argument("reason", StringArgumentType.greedyString())
|
||||
.executes(context -> execute(context, TimeSpan.getTimeSpan(context, "duration"), StringArgumentType.getString(context, "reason")))
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private int execute(CommandContext<CommandSourceStack> context, int seconds, @Nullable String reason) throws CommandSyntaxException {
|
||||
var source = context.getSource();
|
||||
var profile = LocalGameProfile.getProfile(context, "user");
|
||||
|
||||
var data = module.getPlayer(profile.getId());
|
||||
var coreData = Solstice.playerData.get(profile.getId()).getData(CorePlayerData.class);
|
||||
|
||||
if (data.jailed) {
|
||||
source.sendSuccess(() -> module.locale().get("alreadyJailed"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var jailName = StringArgumentType.getString(context, "jail");
|
||||
|
||||
var jails = module.getJails();
|
||||
if (!jails.containsKey(jailName)) {
|
||||
source.sendSuccess(() -> module.locale().get("jailNotFound"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Permissions.check(profile, getPermissionNode("exempt")).thenAccept(granted -> {
|
||||
if (granted) {
|
||||
source.sendSuccess(() -> module.locale().get("playerExempt"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
var player = source.getServer().getPlayerList().getPlayer(profile.getId());
|
||||
|
||||
data.jailed = true;
|
||||
data.jailedBy = source.isPlayer() ? source.getPlayer().getUUID() : new UUID(0L, 0L);
|
||||
data.jailedOn = new Date();
|
||||
data.jailName = jailName;
|
||||
data.jailTime = seconds;
|
||||
data.jailReason = reason;
|
||||
|
||||
if (player != null) {
|
||||
data.previousLocation = new ServerLocation(player);
|
||||
} else {
|
||||
data.previousLocation = coreData.logoffPosition;
|
||||
}
|
||||
|
||||
var map = Map.of(
|
||||
"player", Component.nullToEmpty(profile.getName()),
|
||||
"jail", Component.nullToEmpty(jailName),
|
||||
"duration", Component.nullToEmpty(TimeSpan.toLongString(seconds)),
|
||||
"reason", Component.nullToEmpty(reason)
|
||||
);
|
||||
|
||||
Component text;
|
||||
if (seconds > 0) {
|
||||
if (reason != null) {
|
||||
text = module.locale().get("jailedForWithReason", map);
|
||||
} else {
|
||||
text = module.locale().get("jailedFor", map);
|
||||
}
|
||||
} else {
|
||||
text = module.locale().get("jailed", map);
|
||||
}
|
||||
|
||||
source.sendSuccess(() -> text, true);
|
||||
|
||||
if (player != null) {
|
||||
module.sendToJail(player);
|
||||
}
|
||||
});
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private CompletableFuture<Suggestions> suggestJails(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) {
|
||||
var jails = module.getJails().keySet().stream();
|
||||
return SharedSuggestionProvider.suggest(jails, builder);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
package me.alexdevs.solstice.modules.jail.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.jail.JailModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class JailsCommand extends ModCommand<JailModule> {
|
||||
public JailsCommand(JailModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("jails");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require(2))
|
||||
.executes(this::listJails)
|
||||
.then(Commands.literal("set")
|
||||
.requires(require("set", 3))
|
||||
.then(Commands.argument("name", StringArgumentType.word())
|
||||
.executes(this::createJail)
|
||||
))
|
||||
.then(Commands.literal("delete")
|
||||
.requires(require("set", 3))
|
||||
.then(Commands.argument("name", StringArgumentType.word())
|
||||
.suggests(this::suggestJails)
|
||||
.executes(this::deleteJail)
|
||||
))
|
||||
.then(Commands.literal("tp")
|
||||
.requires(require("tp", 2))
|
||||
.then(Commands.argument("name", StringArgumentType.word())
|
||||
.suggests(this::suggestJails)
|
||||
.executes(this::teleport)
|
||||
));
|
||||
}
|
||||
|
||||
private CompletableFuture<Suggestions> suggestJails(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) {
|
||||
var jails = module.getJails().keySet().stream();
|
||||
return SharedSuggestionProvider.suggest(jails, builder);
|
||||
}
|
||||
|
||||
private int listJails(CommandContext<CommandSourceStack> context) {
|
||||
var jails = module.getJails().keySet().stream().toList();
|
||||
|
||||
if(jails.isEmpty()) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("noJails"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var comma = module.locale().get("comma");
|
||||
var list = Component.empty();
|
||||
|
||||
for(var i = 0; i < jails.size(); i++) {
|
||||
if(i > 0) {
|
||||
list.append(comma);
|
||||
}
|
||||
|
||||
list.append(module.locale().get("listEntry", Map.of(
|
||||
"jail", Component.nullToEmpty(jails.get(i))
|
||||
)));
|
||||
}
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("jailList", Map.of(
|
||||
"list", list
|
||||
)), false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int createJail(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var jailName = StringArgumentType.getString(context, "name");
|
||||
|
||||
var position = new ServerLocation(player);
|
||||
|
||||
var jails = module.getJails();
|
||||
if (jails.containsKey(jailName)) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("jailAlreadyExists"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jails.put(jailName, position);
|
||||
|
||||
var map = Map.of(
|
||||
"jail", Component.nullToEmpty(jailName)
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get("created", map), true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int deleteJail(CommandContext<CommandSourceStack> context) {
|
||||
var jailName = StringArgumentType.getString(context, "name");
|
||||
|
||||
var jails = module.getJails();
|
||||
if (!jails.containsKey(jailName)) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("jailNotFound"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jails.remove(jailName);
|
||||
|
||||
var map = Map.of(
|
||||
"jail", Component.nullToEmpty(jailName)
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get("deleted", map), true);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private int teleport(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
|
||||
var player = context.getSource().getPlayerOrException();
|
||||
var jailName = StringArgumentType.getString(context, "name");
|
||||
var jails = module.getJails();
|
||||
if(!jails.containsKey(jailName)) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("jailNotFound"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var jail = jails.get(jailName);
|
||||
|
||||
var map = Map.of(
|
||||
"jail", Component.nullToEmpty(jailName)
|
||||
);
|
||||
|
||||
context.getSource().sendSuccess(() -> module.locale().get("teleporting", map), true);
|
||||
|
||||
jail.teleport(player);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package me.alexdevs.solstice.modules.jail.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.alexdevs.solstice.api.command.LocalGameProfile;
|
||||
import me.alexdevs.solstice.api.module.ModCommand;
|
||||
import me.alexdevs.solstice.modules.jail.JailModule;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UnjailCommand extends ModCommand<JailModule> {
|
||||
public UnjailCommand(JailModule module) {
|
||||
super(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return List.of("unjail");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<CommandSourceStack> command(String name) {
|
||||
return Commands.literal(name)
|
||||
.requires(require("unjail", 2))
|
||||
.then(Commands.argument("user", StringArgumentType.word())
|
||||
.suggests(LocalGameProfile::suggest)
|
||||
.executes(context -> {
|
||||
var profile = LocalGameProfile.getProfile(context, "user");
|
||||
|
||||
var data = module.getPlayer(profile.getId());
|
||||
|
||||
if (!data.jailed) {
|
||||
context.getSource().sendSuccess(() -> module.locale().get("notJailed"), false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module.unjailPlayer(profile.getId());
|
||||
|
||||
var map = Map.of(
|
||||
"player", Component.nullToEmpty(profile.getName())
|
||||
);
|
||||
context.getSource().sendSuccess(() -> module.locale().get("unjailed", map), false);
|
||||
|
||||
return 1;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package me.alexdevs.solstice.modules.jail.data;
|
||||
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ConfigSerializable
|
||||
public class JailConfig {
|
||||
@Comment("List of commands the jailed players can execute.")
|
||||
public List<String> allowedCommands = List.of(
|
||||
"afk",
|
||||
"ignore",
|
||||
"msg", "tell", "w", "dm", "r", "reply",
|
||||
"mail",
|
||||
"info", "motd", "rules"
|
||||
);
|
||||
|
||||
@Comment("Mute jailed players. They will not be able to send chat messages.")
|
||||
public boolean mute = false;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package me.alexdevs.solstice.modules.jail.data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class JailLocale {
|
||||
public static final Map<String, String> MODULE = Map.ofEntries(
|
||||
Map.entry("jailNotFound", "<gold>This jail does not exist.</gold>"),
|
||||
Map.entry("jailAlreadyExists", "<gold>A jail with this name already exists.</gold>"),
|
||||
Map.entry("teleporting", "<gold>Teleporting to <yellow>${jail}</yellow>...</gold>"),
|
||||
Map.entry("created", "<green>New jail <yellow>${jail}</yellow> created!</green>"),
|
||||
Map.entry("deleted", "<gold>Jail <yellow>${jail}</yellow> deleted!</gold>"),
|
||||
Map.entry("notJailed", "<gold>This user is not jailed!</gold>"),
|
||||
Map.entry("alreadyJailed", "<gold>This player is already jailed!</gold>"),
|
||||
|
||||
Map.entry("jailed", "<gold><yellow>${player}</yellow> has been jailed at <yellow>${jail}</yellow> indefinitely!</gold>"),
|
||||
Map.entry("jailedFor", "<gold><yellow>${player}</yellow> has been jailed at <yellow>${jail}</yellow> for <yellow>${duration}</yellow>!</gold>"),
|
||||
Map.entry("jailedForWithReason", "<gold><yellow>${player}</yellow> has been jailed at <yellow>${jail}</yellow> for <yellow>${duration}</yellow> with reason: <yellow>${reason}</yellow></gold>"),
|
||||
|
||||
Map.entry("playerJailed", "<red>You have been jailed!</red>"),
|
||||
Map.entry("playerJailedFor", "<red>You have been jailed for <yellow>${duration}</yellow>!</red>"),
|
||||
Map.entry("playerJailedForWithReason", "<red>You have been jailed for <yellow>${duration}</yellow> with reason: <yellow>${reason}</yellow></red>"),
|
||||
Map.entry("playerUnjailed", "<green>You have been unjailed!</green>"),
|
||||
Map.entry("unjailed", "<gold>Unjailed <yellow>${player}</yellow>!</gold>"),
|
||||
|
||||
Map.entry("cannotRunCommands", "<red>You are not allowed to run this command in jail!</red>"),
|
||||
Map.entry("cannotBreakBlocks", "<red>You are not allowed to break blocks in jail!</red>"),
|
||||
Map.entry("cannotAttackEntities", "<red>You are not allowed to attack entities in jail!</red>"),
|
||||
Map.entry("cannotUseBlocks", "<red>You are not allowed to use blocks in jail!</red>"),
|
||||
Map.entry("cannotUseEntities", "<red>You are not allowed to interact with entities in jail!</red>"),
|
||||
Map.entry("cannotUseItems", "<red>You are not allowed to use items in jail!</red>"),
|
||||
Map.entry("cannotSpeak", "<red>You are not allowed to speak in jail!</red>"),
|
||||
|
||||
Map.entry("playerExempt", "<gold>This player is exempt from being jailed!</gold>"),
|
||||
|
||||
Map.entry("jailList", "<gold>Jails: ${list}.</gold>"),
|
||||
Map.entry("listEntry", "<yellow>${jail}</yellow>"),
|
||||
Map.entry("comma", "<gold>, </gold>"),
|
||||
Map.entry("noJails", "<gold>There are no jails yet.</gold>"),
|
||||
|
||||
Map.entry("infoHeader", "<gold><yellow>${player}</yellow> Jail Information:</gold>"),
|
||||
Map.entry("infoJailedAt", "<gold>Jailed at: <yellow>${jail}</yellow></gold>"),
|
||||
Map.entry("infoJailedBy", "<gold>Jailed by: <yellow>${operator}</yellow></gold>"),
|
||||
Map.entry("infoJailReason", "<gold>Reason: <yellow>${reason}</yellow></gold>"),
|
||||
Map.entry("infoJailReasonEmpty", "No reason"),
|
||||
Map.entry("infoJailedFor", "<gold>Jail time: <yellow>${duration}</yellow></gold>"),
|
||||
Map.entry("infoJailedForEmpty", "Indefinitely"),
|
||||
Map.entry("infoJailedOn", "<gold>Jailed on: <yellow>${date}</yellow></gold>")
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package me.alexdevs.solstice.modules.jail.data;
|
||||
|
||||
import me.alexdevs.solstice.api.ServerLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
public class JailPlayerData {
|
||||
public boolean jailed = false;
|
||||
public @Nullable String jailName = null;
|
||||
public @Nullable UUID jailedBy = null;
|
||||
public @Nullable Date jailedOn = null;
|
||||
public int jailTime = 0;
|
||||
public @Nullable String jailReason = null;
|
||||
public @Nullable ServerLocation previousLocation = null;
|
||||
public boolean teleportToPreviousLocation = false;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue