Add AFK and active time support
This commit is contained in:
parent
1d353f89f5
commit
d07fade5ab
10 changed files with 227 additions and 47 deletions
|
@ -18,6 +18,7 @@ repositories {
|
||||||
// for more information about repositories.
|
// for more information about repositories.
|
||||||
|
|
||||||
maven { url 'https://maven.wispforest.io' }
|
maven { url 'https://maven.wispforest.io' }
|
||||||
|
maven { url 'https://maven.nucleoid.xyz' }
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
|
@ -44,7 +45,7 @@ dependencies {
|
||||||
include "io.wispforest:owo-sentinel:${project.owo_version}"
|
include "io.wispforest:owo-sentinel:${project.owo_version}"
|
||||||
|
|
||||||
compileOnly "net.luckperms:api:${project.luckpermsapi_version}"
|
compileOnly "net.luckperms:api:${project.luckpermsapi_version}"
|
||||||
|
include modImplementation("me.lucko:fabric-permissions-api:${project.permissions_api_version}")
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
|
|
|
@ -9,7 +9,7 @@ yarn_mappings=1.20.1+build.10
|
||||||
loader_version=0.16.5
|
loader_version=0.16.5
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.9.1
|
mod_version=1.9.2
|
||||||
maven_group=cc.reconnected
|
maven_group=cc.reconnected
|
||||||
archives_base_name=rcc-server
|
archives_base_name=rcc-server
|
||||||
|
|
||||||
|
@ -18,4 +18,5 @@ fabric_version=0.92.2+1.20.1
|
||||||
|
|
||||||
owo_version=0.11.2+1.20
|
owo_version=0.11.2+1.20
|
||||||
|
|
||||||
luckpermsapi_version=5.4
|
luckpermsapi_version=5.4
|
||||||
|
permissions_api_version=0.2-SNAPSHOT
|
|
@ -1,5 +1,6 @@
|
||||||
package cc.reconnected.server;
|
package cc.reconnected.server;
|
||||||
|
|
||||||
|
import cc.reconnected.server.commands.AfkCommand;
|
||||||
import cc.reconnected.server.commands.RccCommand;
|
import cc.reconnected.server.commands.RccCommand;
|
||||||
import cc.reconnected.server.database.PlayerData;
|
import cc.reconnected.server.database.PlayerData;
|
||||||
import cc.reconnected.server.events.PlayerActivityEvents;
|
import cc.reconnected.server.events.PlayerActivityEvents;
|
||||||
|
@ -9,13 +10,13 @@ import cc.reconnected.server.http.ServiceServer;
|
||||||
import cc.reconnected.server.trackers.AfkTracker;
|
import cc.reconnected.server.trackers.AfkTracker;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
|
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.luckperms.api.LuckPerms;
|
import net.luckperms.api.LuckPerms;
|
||||||
import net.luckperms.api.LuckPermsProvider;
|
import net.luckperms.api.LuckPermsProvider;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
@ -78,6 +79,7 @@ public class RccServer implements ModInitializer {
|
||||||
LOGGER.info("Starting rcc-server");
|
LOGGER.info("Starting rcc-server");
|
||||||
|
|
||||||
CommandRegistrationCallback.EVENT.register(RccCommand::register);
|
CommandRegistrationCallback.EVENT.register(RccCommand::register);
|
||||||
|
CommandRegistrationCallback.EVENT.register(AfkCommand::register);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serviceServer = new ServiceServer();
|
serviceServer = new ServiceServer();
|
||||||
|
@ -124,6 +126,13 @@ public class RccServer implements ModInitializer {
|
||||||
currentPlayerCount = server.getCurrentPlayerCount() - 1;
|
currentPlayerCount = server.getCurrentPlayerCount() - 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PlayerActivityEvents.AFK.register((player, server) -> {
|
||||||
|
LOGGER.info("{} is AFK. Active time: {} seconds.", player, afkTracker.getActiveTime(player));
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerActivityEvents.AFK_RETURN.register((player, server) -> {
|
||||||
|
LOGGER.info("{} is no longer AFK. Active time: {} seconds.", player, afkTracker.getActiveTime(player));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcastMessage(MinecraftServer server, Text message) {
|
public void broadcastMessage(MinecraftServer server, Text message) {
|
||||||
|
@ -131,4 +140,16 @@ public class RccServer implements ModInitializer {
|
||||||
player.sendMessage(message, false);
|
player.sendMessage(message, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPlayerAfk(PlayerEntity player) {
|
||||||
|
return afkTracker.isPlayerAfk(player.getUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayerAfk(ServerPlayerEntity player, boolean afk) {
|
||||||
|
afkTracker.setPlayerAfk(player, afk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActiveTime(ServerPlayerEntity player) {
|
||||||
|
return afkTracker().getActiveTime(player);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,5 +4,8 @@ import io.wispforest.owo.config.annotation.Config;
|
||||||
|
|
||||||
@Config(name = "rcc-server-config", wrapperName = "RccServerConfig")
|
@Config(name = "rcc-server-config", wrapperName = "RccServerConfig")
|
||||||
public class RccServerConfigModel {
|
public class RccServerConfigModel {
|
||||||
public short httpPort = 25581;
|
public boolean enableHttpApi = true;
|
||||||
|
public int httpPort = 25581;
|
||||||
|
|
||||||
|
public int afkTimeTrigger = 300;
|
||||||
}
|
}
|
||||||
|
|
32
src/main/java/cc/reconnected/server/commands/AfkCommand.java
Normal file
32
src/main/java/cc/reconnected/server/commands/AfkCommand.java
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package cc.reconnected.server.commands;
|
||||||
|
|
||||||
|
import cc.reconnected.server.RccServer;
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import me.lucko.fabric.api.permissions.v0.Permissions;
|
||||||
|
import net.minecraft.command.CommandRegistryAccess;
|
||||||
|
import net.minecraft.server.command.CommandManager;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
|
|
||||||
|
public class AfkCommand {
|
||||||
|
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess registryAccess, CommandManager.RegistrationEnvironment environment) {
|
||||||
|
var rootCommand = literal("afk")
|
||||||
|
.requires(Permissions.require("rcc.afk.command", true))
|
||||||
|
.executes(context -> {
|
||||||
|
|
||||||
|
if(!context.getSource().isExecutedByPlayer()) {
|
||||||
|
context.getSource().sendFeedback(() -> Text.of("This command can only be executed by players!"), false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var player = context.getSource().getPlayer();
|
||||||
|
RccServer.getInstance().setPlayerAfk(player, true);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatcher.register(rootCommand);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
package cc.reconnected.server.commands;
|
package cc.reconnected.server.commands;
|
||||||
|
|
||||||
import cc.reconnected.server.RccServer;
|
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.command.CommandRegistryAccess;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.server.command.CommandManager.literal;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package cc.reconnected.server.data;
|
||||||
|
|
||||||
|
import cc.reconnected.server.RccServer;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.PersistentState;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class StateSaverAndLoader extends PersistentState {
|
||||||
|
public final HashMap<UUID, WorldPlayerData> players = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NbtCompound writeNbt(NbtCompound nbt) {
|
||||||
|
var playersNbt = new NbtCompound();
|
||||||
|
players.forEach((uuid, data) -> {
|
||||||
|
var playerNbt = new NbtCompound();
|
||||||
|
playerNbt.putInt("activeTime", data.activeTime);
|
||||||
|
playersNbt.put(uuid.toString(), playerNbt);
|
||||||
|
});
|
||||||
|
nbt.put("players", playersNbt);
|
||||||
|
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StateSaverAndLoader createFromNbt(NbtCompound nbt) {
|
||||||
|
var state = new StateSaverAndLoader();
|
||||||
|
|
||||||
|
var playersNbt = nbt.getCompound("players");
|
||||||
|
playersNbt.getKeys().forEach(key -> {
|
||||||
|
var playerData = new WorldPlayerData();
|
||||||
|
|
||||||
|
playerData.activeTime = playersNbt.getCompound(key).getInt("activeTime");
|
||||||
|
UUID uuid = UUID.fromString(key);
|
||||||
|
state.players.put(uuid, playerData);
|
||||||
|
});
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StateSaverAndLoader getServerState(MinecraftServer server) {
|
||||||
|
var persistentStateManager = server.getWorld(World.OVERWORLD).getPersistentStateManager();
|
||||||
|
var state = persistentStateManager.getOrCreate(
|
||||||
|
StateSaverAndLoader::createFromNbt,
|
||||||
|
StateSaverAndLoader::new,
|
||||||
|
RccServer.MOD_ID
|
||||||
|
);
|
||||||
|
state.markDirty();
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WorldPlayerData getPlayerState(LivingEntity player) {
|
||||||
|
var serverState = getServerState(player.getWorld().getServer());
|
||||||
|
return serverState.players.computeIfAbsent(player.getUuid(), uuid -> new WorldPlayerData());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package cc.reconnected.server.data;
|
||||||
|
|
||||||
|
public class WorldPlayerData {
|
||||||
|
public int activeTime = 0;
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ public class PlayerData {
|
||||||
public static final String pronouns = "pronouns";
|
public static final String pronouns = "pronouns";
|
||||||
public static final String firstJoinedDate = "first_joined_date";
|
public static final String firstJoinedDate = "first_joined_date";
|
||||||
public static final String supporterLevel = "supporter_level";
|
public static final String supporterLevel = "supporter_level";
|
||||||
|
public static final String activeTime = "active_time";
|
||||||
}
|
}
|
||||||
|
|
||||||
private final User lpUser;
|
private final User lpUser;
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package cc.reconnected.server.trackers;
|
package cc.reconnected.server.trackers;
|
||||||
|
|
||||||
import cc.reconnected.server.RccServer;
|
import cc.reconnected.server.RccServer;
|
||||||
|
import cc.reconnected.server.data.StateSaverAndLoader;
|
||||||
|
import cc.reconnected.server.database.PlayerData;
|
||||||
import cc.reconnected.server.events.PlayerActivityEvents;
|
import cc.reconnected.server.events.PlayerActivityEvents;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
import net.fabricmc.fabric.api.event.player.*;
|
import net.fabricmc.fabric.api.event.player.*;
|
||||||
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents;
|
||||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
|
@ -16,11 +17,10 @@ import java.util.HashMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class AfkTracker {
|
public class AfkTracker {
|
||||||
private static final int cycleDelay = 10;
|
private static final int cycleDelay = 1;
|
||||||
private static final int absentTimeTrigger = 300 * 20; // 5 mins (* 20 ticks)
|
private static final int absentTimeTrigger = RccServer.CONFIG.afkTimeTrigger() * 20; // seconds * 20 ticks
|
||||||
private final HashMap<UUID, PlayerPosition> playerPositions = new HashMap<>();
|
|
||||||
private final HashMap<UUID, Integer> playerLastUpdate = new HashMap<>();
|
private final HashMap<UUID, PlayerState> playerStates = new HashMap<>();
|
||||||
private final HashMap<UUID, Boolean> playerAfkStates = new HashMap<>();
|
|
||||||
|
|
||||||
public AfkTracker() {
|
public AfkTracker() {
|
||||||
ServerTickEvents.END_SERVER_TICK.register(server -> {
|
ServerTickEvents.END_SERVER_TICK.register(server -> {
|
||||||
|
@ -31,16 +31,18 @@ public class AfkTracker {
|
||||||
|
|
||||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
|
||||||
final var player = handler.getPlayer();
|
final var player = handler.getPlayer();
|
||||||
var playerPosition = new PlayerPosition(player);
|
playerStates.put(player.getUuid(), new PlayerState(player, server.getTicks()));
|
||||||
playerPositions.put(player.getUuid(), playerPosition);
|
|
||||||
playerLastUpdate.put(player.getUuid(), server.getTicks());
|
|
||||||
playerAfkStates.put(player.getUuid(), false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
|
||||||
playerPositions.remove(handler.getPlayer().getUuid());
|
updatePlayerActiveTime(handler.getPlayer(), server.getTicks());
|
||||||
playerLastUpdate.remove(handler.getPlayer().getUuid());
|
playerStates.remove(handler.getPlayer().getUuid());
|
||||||
playerAfkStates.remove(handler.getPlayer().getUuid());
|
|
||||||
|
// sync to LP
|
||||||
|
var activeTime = String.valueOf(getActiveTime(handler.getPlayer()));
|
||||||
|
var playerData = PlayerData.getPlayer(handler.getPlayer());
|
||||||
|
|
||||||
|
playerData.set(PlayerData.KEYS.activeTime, activeTime).join();
|
||||||
});
|
});
|
||||||
|
|
||||||
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
|
AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
|
||||||
|
@ -74,46 +76,60 @@ public class AfkTracker {
|
||||||
});
|
});
|
||||||
|
|
||||||
ServerMessageEvents.ALLOW_COMMAND_MESSAGE.register((message, source, params) -> {
|
ServerMessageEvents.ALLOW_COMMAND_MESSAGE.register((message, source, params) -> {
|
||||||
if(!source.isExecutedByPlayer())
|
if (!source.isExecutedByPlayer())
|
||||||
return true;
|
return true;
|
||||||
resetAfkState(source.getPlayer(), source.getServer());
|
resetAfkState(source.getPlayer(), source.getServer());
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePlayers(MinecraftServer server) {
|
|
||||||
var players = server.getPlayerManager().getPlayerList();
|
private void updatePlayer(ServerPlayerEntity player, MinecraftServer server) {
|
||||||
var currentTick = server.getTicks();
|
var currentTick = server.getTicks();
|
||||||
|
var playerState = playerStates.computeIfAbsent(player.getUuid(), uuid -> new PlayerState(player, currentTick));
|
||||||
|
|
||||||
|
var oldPosition = playerState.position;
|
||||||
|
var newPosition = new PlayerPosition(player);
|
||||||
|
if (!oldPosition.equals(newPosition)) {
|
||||||
|
playerState.position = newPosition;
|
||||||
|
resetAfkState(player, server);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerState.isAfk)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((playerState.lastUpdate + absentTimeTrigger) <= currentTick) {
|
||||||
|
// player is afk after 5 mins
|
||||||
|
updatePlayerActiveTime(player, currentTick);
|
||||||
|
playerState.isAfk = true;
|
||||||
|
PlayerActivityEvents.AFK.invoker().onAfk(player, server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePlayerActiveTime(ServerPlayerEntity player, int currentTick) {
|
||||||
|
var playerState = playerStates.get(player.getUuid());
|
||||||
|
if(!playerState.isAfk) {
|
||||||
|
var worldPlayerData = StateSaverAndLoader.getPlayerState(player);
|
||||||
|
var interval = currentTick - playerState.activeStart;
|
||||||
|
worldPlayerData.activeTime += interval / 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePlayers(MinecraftServer server) {
|
||||||
|
var players = server.getPlayerManager().getPlayerList();
|
||||||
players.forEach(player -> {
|
players.forEach(player -> {
|
||||||
if (!playerPositions.containsKey(player.getUuid())) {
|
updatePlayer(player, server);
|
||||||
playerPositions.put(player.getUuid(), new PlayerPosition(player));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var oldPosition = playerPositions.get(player.getUuid());
|
|
||||||
var newPosition = new PlayerPosition(player);
|
|
||||||
if (!oldPosition.equals(newPosition)) {
|
|
||||||
playerPositions.put(player.getUuid(), newPosition);
|
|
||||||
resetAfkState(player, server);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playerAfkStates.get(player.getUuid())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((playerLastUpdate.get(player.getUuid()) + absentTimeTrigger) <= currentTick) {
|
|
||||||
// player is afk after 5 mins
|
|
||||||
playerAfkStates.put(player.getUuid(), true);
|
|
||||||
PlayerActivityEvents.AFK.invoker().onAfk(player, server);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetAfkState(ServerPlayerEntity player, MinecraftServer server) {
|
private void resetAfkState(ServerPlayerEntity player, MinecraftServer server) {
|
||||||
playerLastUpdate.put(player.getUuid(), server.getTicks());
|
var playerState = playerStates.get(player.getUuid());
|
||||||
if (playerAfkStates.get(player.getUuid())) {
|
playerState.lastUpdate = server.getTicks();
|
||||||
|
if (playerState.isAfk) {
|
||||||
|
playerState.isAfk = false;
|
||||||
|
playerState.activeStart = server.getTicks();
|
||||||
PlayerActivityEvents.AFK_RETURN.invoker().onAfkReturn(player, server);
|
PlayerActivityEvents.AFK_RETURN.invoker().onAfkReturn(player, server);
|
||||||
playerAfkStates.put(player.getUuid(), false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,4 +157,47 @@ public class AfkTracker {
|
||||||
pitch = player.getPitch();
|
pitch = player.getPitch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class PlayerState {
|
||||||
|
public PlayerPosition position;
|
||||||
|
public int lastUpdate;
|
||||||
|
public boolean isAfk;
|
||||||
|
public int activeStart;
|
||||||
|
|
||||||
|
public PlayerState(ServerPlayerEntity player, int lastUpdate) {
|
||||||
|
this.position = new PlayerPosition(player);
|
||||||
|
this.lastUpdate = lastUpdate;
|
||||||
|
this.isAfk = false;
|
||||||
|
this.activeStart = lastUpdate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPlayerAfk(UUID playerUuid) {
|
||||||
|
if (!playerStates.containsKey(playerUuid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return playerStates.get(playerUuid).isAfk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayerAfk(ServerPlayerEntity player, boolean afk) {
|
||||||
|
if (!playerStates.containsKey(player.getUuid())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var server = player.getWorld().getServer();
|
||||||
|
|
||||||
|
if (afk) {
|
||||||
|
playerStates.get(player.getUuid()).lastUpdate = -absentTimeTrigger - 20; // just to be sure
|
||||||
|
} else {
|
||||||
|
resetAfkState(player, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePlayer(player, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActiveTime(ServerPlayerEntity player) {
|
||||||
|
var worldPlayerData = StateSaverAndLoader.getPlayerState(player);
|
||||||
|
return worldPlayerData.activeTime;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue