9
0
mirror of https://github.com/Xiao-MoMi/Custom-Nameplates.git synced 2025-12-25 18:09:20 +00:00
This commit is contained in:
Xiao-MoMi
2023-03-29 20:42:23 +08:00
parent b980a4df65
commit 4056dde611
31 changed files with 106 additions and 86 deletions

View File

@@ -20,11 +20,9 @@ package net.momirealms.customnameplates.listener.packet;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.manager.ActionBarManager;
import net.momirealms.customnameplates.object.nameplate.mode.PacketsHandler;
public class ActionBarListener extends PacketAdapter {
@@ -36,6 +34,6 @@ public class ActionBarListener extends PacketAdapter {
}
public void onPacketSending(PacketEvent event) {
actionBarManager.onReceivePacket(event);
actionBarManager.onReceiveActionBarPacket(event);
}
}

View File

@@ -0,0 +1,22 @@
package net.momirealms.customnameplates.listener.packet;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.manager.ActionBarManager;
public class SystemChatListener extends PacketAdapter {
private final ActionBarManager actionBarManager;
public SystemChatListener(ActionBarManager actionBarManager) {
super(CustomNameplates.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Server.SYSTEM_CHAT);
this.actionBarManager = actionBarManager;
}
public void onPacketSending(PacketEvent event) {
actionBarManager.onReceiveSystemChatPacket(event);
}
}

View File

@@ -22,11 +22,11 @@ import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ScoreComponent;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.listener.JoinQuitListener;
import net.momirealms.customnameplates.listener.packet.ActionBarListener;
import net.momirealms.customnameplates.listener.packet.SystemChatListener;
import net.momirealms.customnameplates.object.Function;
import net.momirealms.customnameplates.object.actionbar.ActionBarConfig;
import net.momirealms.customnameplates.object.actionbar.ActionBarTask;
@@ -49,6 +49,7 @@ public class ActionBarManager extends Function {
private final LinkedHashMap<String, ActionBarConfig> actionBarConfigMap;
private final ConcurrentHashMap<UUID, ActionBarTask> actionBarTaskMap;
private final ActionBarListener actionBarListener;
private final SystemChatListener systemChatListener;
private final JoinQuitListener joinQuitListener;
private final CustomNameplates plugin;
@@ -58,6 +59,7 @@ public class ActionBarManager extends Function {
this.actionBarTaskMap = new ConcurrentHashMap<>();
this.joinQuitListener = new JoinQuitListener(this);
this.actionBarListener = new ActionBarListener(this);
this.systemChatListener = new SystemChatListener(this);
}
@Override
@@ -66,6 +68,7 @@ public class ActionBarManager extends Function {
this.loadConfig();
Bukkit.getPluginManager().registerEvents(joinQuitListener, plugin);
CustomNameplates.getProtocolManager().addPacketListener(actionBarListener);
CustomNameplates.getProtocolManager().addPacketListener(systemChatListener);
for (Player player : Bukkit.getOnlinePlayers()) {
onJoin(player);
}
@@ -78,6 +81,7 @@ public class ActionBarManager extends Function {
}
actionBarConfigMap.clear();
CustomNameplates.getProtocolManager().removePacketListener(actionBarListener);
CustomNameplates.getProtocolManager().removePacketListener(systemChatListener);
HandlerList.unregisterAll(joinQuitListener);
}
@@ -113,7 +117,7 @@ public class ActionBarManager extends Function {
AdventureUtils.consoleMessage("[CustomNameplates] Loaded <green>" + actionBarConfigMap.size() + " <gray>actionbars");
}
public void onReceivePacket(PacketEvent event) {
public void onReceiveActionBarPacket(PacketEvent event) {
PacketContainer packet = event.getPacket();
WrappedChatComponent wrappedChatComponent = packet.getChatComponents().read(0);
if (wrappedChatComponent != null) {
@@ -131,6 +135,27 @@ public class ActionBarManager extends Function {
}
}
public void onReceiveSystemChatPacket(PacketEvent event) {
PacketContainer packet = event.getPacket();
// 1.19+
Boolean overlay = packet.getBooleans().readSafely(0);
// lower version
Integer position = packet.getIntegers().readSafely(0);
if ((overlay != null && overlay || position != null && position == 2)) {
ActionBarTask actionBarTask = getActionBarTask(event.getPlayer().getUniqueId());
if (actionBarTask != null) {
Component component = GsonComponentSerializer.gson().deserialize(packet.getStrings().read(0));
if (component instanceof ScoreComponent scoreComponent) {
if (scoreComponent.name().equals("nameplates") && scoreComponent.objective().equals("actionbar")) {
return;
}
}
event.setCancelled(true);
actionBarTask.setOtherText(AdventureUtils.getMiniMessageFormat(component), System.currentTimeMillis());
}
}
}
public String getOtherPluginActionBarText(Player player) {
ActionBarTask actionBarTask = getActionBarTask(player.getUniqueId());
if (actionBarTask != null) {

View File

@@ -6,7 +6,6 @@ import net.momirealms.customnameplates.object.ConditionalText;
import net.momirealms.customnameplates.object.Function;
import net.momirealms.customnameplates.object.SimpleChar;
import net.momirealms.customnameplates.object.armorstand.ArmorStandManager;
import net.momirealms.customnameplates.object.bubble.BubbleConfig;
import net.momirealms.customnameplates.object.font.OffsetFont;
import net.momirealms.customnameplates.object.nameplate.NameplateConfig;
import net.momirealms.customnameplates.object.nameplate.mode.AbstractNameplateTag;

View File

@@ -2,9 +2,7 @@ package net.momirealms.customnameplates.object.actionbar;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ScoreComponent;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.momirealms.customnameplates.object.DynamicText;
import net.momirealms.customnameplates.object.requirements.PlayerCondition;
import net.momirealms.customnameplates.object.requirements.Requirement;
import net.momirealms.customnameplates.utils.AdventureUtils;
import org.bukkit.entity.Player;
@@ -17,10 +15,8 @@ public class ActionBarSender {
private int current_text_id;
private final DynamicText[] dynamicTexts;
private final Requirement[] requirements;
private final ActionBarTask actionBarTask;
public ActionBarSender(int switch_interval, String[] texts, Requirement[] requirements, Player player, ActionBarTask actionBarTask) {
this.actionBarTask = actionBarTask;
public ActionBarSender(int switch_interval, String[] texts, Requirement[] requirements, Player player) {
this.player = player;
this.switch_interval = switch_interval;
this.requirements = requirements;
@@ -31,10 +27,10 @@ public class ActionBarSender {
this.current_text_id = 0;
}
public boolean canSend(PlayerCondition playerCondition) {
public boolean canSend() {
if (requirements.length == 0) return true;
for (Requirement requirement : requirements) {
if (!requirement.isConditionMet(playerCondition)) {
if (!requirement.isConditionMet(player)) {
return false;
}
}

View File

@@ -1,7 +1,6 @@
package net.momirealms.customnameplates.object.actionbar;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.object.requirements.PlayerCondition;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
@@ -12,10 +11,8 @@ public class ActionBarTask {
private final ActionBarSender[] actionBarSenders;
private String otherText;
private long expireTime;
private final Player player;
public ActionBarTask(Player player, ActionBarConfig[] configs) {
this.player = player;
this.actionBarSenders = new ActionBarSender[configs.length];
this.otherText = "";
for (int i = 0; i < configs.length; i++) {
@@ -24,8 +21,7 @@ public class ActionBarTask {
actionBarConfig.getInterval(),
actionBarConfig.getTexts(),
actionBarConfig.getConditions(),
player,
this
player
);
}
}
@@ -39,9 +35,8 @@ public class ActionBarTask {
if (System.currentTimeMillis() > getExpireTime()) {
this.otherText = "";
}
PlayerCondition playerCondition = new PlayerCondition(player);
for (ActionBarSender actionBarSender : actionBarSenders) {
if (actionBarSender.canSend(playerCondition)) {
if (actionBarSender.canSend()) {
actionBarSender.send();
return;
}

View File

@@ -25,7 +25,6 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.google.common.collect.Lists;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.object.DynamicText;
import net.momirealms.customnameplates.object.requirements.PlayerCondition;
import net.momirealms.customnameplates.object.requirements.Requirement;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
@@ -76,7 +75,7 @@ public class FakeArmorStand {
public boolean canShow() {
if (requirements == null) return true;
for (Requirement requirement : requirements) {
if (!requirement.isConditionMet(new PlayerCondition(owner))) {
if (!requirement.isConditionMet(owner)) {
return false;
}
}

View File

@@ -9,7 +9,6 @@ import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.object.DynamicText;
import net.momirealms.customnameplates.object.requirements.PlayerCondition;
import net.momirealms.customnameplates.object.requirements.Requirement;
import net.momirealms.customnameplates.utils.AdventureUtils;
import org.bukkit.boss.BarColor;
@@ -53,10 +52,10 @@ public class BossBarSender {
return isShown;
}
public boolean canSend(PlayerCondition playerCondition) {
public boolean canSend() {
if (requirements.length == 0) return true;
for (Requirement requirement : requirements) {
if (!requirement.isConditionMet(playerCondition)) {
if (!requirement.isConditionMet(player)) {
return false;
}
}

View File

@@ -1,7 +1,6 @@
package net.momirealms.customnameplates.object.bossbar;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.object.requirements.PlayerCondition;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
@@ -37,9 +36,8 @@ public class BossBarTask {
public void start() {
this.timerTask = Bukkit.getScheduler().runTaskTimerAsynchronously(CustomNameplates.getInstance(), () -> {
PlayerCondition playerCondition = new PlayerCondition(player);
for (BossBarSender bossBarSender : bossBarSenders) {
if (!bossBarSender.canSend(playerCondition)) {
if (!bossBarSender.canSend()) {
if (bossBarSender.isShown()) {
bossBarSender.hide();
return;

View File

@@ -21,7 +21,6 @@ import me.clip.placeholderapi.PlaceholderAPI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.momirealms.customnameplates.CustomNameplates;
import net.momirealms.customnameplates.manager.ConfigManager;
import net.momirealms.customnameplates.manager.NameplateManager;
import net.momirealms.customnameplates.object.DynamicText;
import net.momirealms.customnameplates.utils.AdventureUtils;

View File

@@ -1,7 +1,6 @@
package net.momirealms.customnameplates.object.placeholders;
import net.momirealms.customnameplates.object.ConditionalText;
import net.momirealms.customnameplates.object.requirements.PlayerCondition;
import net.momirealms.customnameplates.object.requirements.Requirement;
import org.bukkit.entity.Player;
@@ -14,11 +13,10 @@ public class ConditionalTexts {
}
public String getValue(Player player) {
PlayerCondition playerCondition = new PlayerCondition(player);
outer:
for (ConditionalText conditionalText : conditionalTexts) {
for (Requirement requirement : conditionalText.getRequirements()) {
if (!requirement.isConditionMet(playerCondition)) {
if (!requirement.isConditionMet(player)) {
continue outer;
}
}

View File

@@ -33,8 +33,6 @@ import org.bukkit.World;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public class NameplatePlaceholders extends PlaceholderExpansion {
private final PlaceholderManager placeholderManager;

View File

@@ -18,13 +18,14 @@
package net.momirealms.customnameplates.object.requirements;
import net.momirealms.biomeapi.BiomeAPI;
import org.bukkit.entity.Player;
import java.util.HashSet;
public record BiomeImpl(HashSet<String> biomes) implements Requirement {
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
return biomes.contains(BiomeAPI.getBiome(playerCondition.getPlayer().getLocation()));
public boolean isConditionMet(Player player) {
return biomes.contains(BiomeAPI.getBiome(player.getLocation()));
}
}

View File

@@ -19,15 +19,14 @@ package net.momirealms.customnameplates.object.requirements;
import net.momirealms.customnameplates.object.requirements.papi.*;
import org.bukkit.configuration.MemorySection;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class CustomPapiImpl implements Requirement {
public static HashSet<String> allPapi = new HashSet<>();
private final List<PapiRequirement> papiRequirement;
public CustomPapiImpl(Map<String, Object> expressions){
@@ -35,9 +34,9 @@ public class CustomPapiImpl implements Requirement {
}
@Override
public boolean isConditionMet(PlayerCondition condition) {
public boolean isConditionMet(Player player) {
for (PapiRequirement requirement : papiRequirement) {
if (!requirement.isMet(condition.getPapiMap(), condition.getPlayer())) {
if (!requirement.isMet(player)) {
return false;
}
}
@@ -61,7 +60,6 @@ public class CustomPapiImpl implements Requirement {
String papi = map2.getString("papi");
String value = map2.getString("value");
if (value == null || papi == null || type == null) return;
allPapi.add(papi);
switch (type){
case "==" -> papiRequirements.add(new PapiEquals(papi, value));
case "!=" -> papiRequirements.add(new PapiNotEquals(papi, value));

View File

@@ -1,12 +1,14 @@
package net.momirealms.customnameplates.object.requirements;
import org.bukkit.entity.Player;
import java.util.Calendar;
import java.util.HashSet;
public record DateImpl(HashSet<String> dates) implements Requirement {
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
public boolean isConditionMet(Player player) {
Calendar calendar = Calendar.getInstance();
String current = (calendar.get(Calendar.MONTH) + 1) + "/" + calendar.get(Calendar.DATE);
return dates.contains(current);

View File

@@ -17,6 +17,8 @@
package net.momirealms.customnameplates.object.requirements;
import org.bukkit.entity.Player;
public record PermissionImpl(String permission) implements Requirement {
public String getPermission() {
@@ -24,7 +26,7 @@ public record PermissionImpl(String permission) implements Requirement {
}
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
return playerCondition.getPlayer().hasPermission(permission);
public boolean isConditionMet(Player player) {
return player.hasPermission(permission);
}
}

View File

@@ -17,6 +17,8 @@
package net.momirealms.customnameplates.object.requirements;
import org.bukkit.entity.Player;
public interface Requirement {
boolean isConditionMet(PlayerCondition playerCondition);
boolean isConditionMet(Player player);
}

View File

@@ -18,6 +18,7 @@
package net.momirealms.customnameplates.object.requirements;
import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Player;
import java.util.List;
@@ -28,8 +29,8 @@ public record TimeImpl(List<String> times) implements Requirement{
}
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
long time = playerCondition.getPlayer().getWorld().getTime();
public boolean isConditionMet(Player player) {
long time = player.getWorld().getTime();
for (String range : times) {
String[] timeMinMax = StringUtils.split(range, "~");
if (time > Long.parseLong(timeMinMax[0]) && time < Long.parseLong(timeMinMax[1])) {

View File

@@ -18,6 +18,7 @@
package net.momirealms.customnameplates.object.requirements;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.List;
@@ -28,8 +29,8 @@ public record WeatherImpl(List<String> weathers) implements Requirement {
}
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
World world = playerCondition.getPlayer().getWorld();
public boolean isConditionMet(Player player) {
World world = player.getWorld();
String currentWeather;
if (world.isThundering()) {
if (world.isClearWeather()) currentWeather = "thunder";

View File

@@ -17,6 +17,8 @@
package net.momirealms.customnameplates.object.requirements;
import org.bukkit.entity.Player;
import java.util.List;
public record WorldImpl(List<String> worlds) implements Requirement {
@@ -26,8 +28,8 @@ public record WorldImpl(List<String> worlds) implements Requirement {
}
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
org.bukkit.World world = playerCondition.getPlayer().getWorld();
public boolean isConditionMet(Player player) {
org.bukkit.World world = player.getWorld();
return worlds.contains(world.getName());
}
}

View File

@@ -18,6 +18,7 @@
package net.momirealms.customnameplates.object.requirements;
import org.apache.commons.lang.StringUtils;
import org.bukkit.entity.Player;
import java.util.List;
@@ -28,8 +29,8 @@ public record YPosImpl(List<String> yPos) implements Requirement {
}
@Override
public boolean isConditionMet(PlayerCondition playerCondition) {
int y = (int) playerCondition.getPlayer().getLocation().getY();
public boolean isConditionMet(Player player) {
int y = (int) player.getLocation().getY();
for (String range : yPos) {
String[] yMinMax = StringUtils.split(range, "~");
if (y > Integer.parseInt(yMinMax[0]) && y < Integer.parseInt(yMinMax[1])) {

View File

@@ -19,15 +19,14 @@ package net.momirealms.customnameplates.object.requirements.papi;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.List;
public record ExpressionAnd(List<PapiRequirement> requirements) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
public boolean isMet(Player player) {
for (PapiRequirement requirement : requirements) {
if (!requirement.isMet(papiMap, player)) return false;
if (!requirement.isMet(player)) return false;
}
return true;
}

View File

@@ -19,15 +19,14 @@ package net.momirealms.customnameplates.object.requirements.papi;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.List;
public record ExpressionOr(List<PapiRequirement> requirements) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
public boolean isMet(Player player) {
for (PapiRequirement requirement : requirements) {
if (requirement.isMet(papiMap, player)) return true;
if (requirement.isMet(player)) return true;
}
return false;
}

View File

@@ -20,14 +20,13 @@ package net.momirealms.customnameplates.object.requirements.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Objects;
public record PapiEquals(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
String value = papiMap.get(papi);
public boolean isMet(Player player) {
String value = PlaceholderAPI.setPlaceholders(player, papi);
return Objects.equals(value, PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -20,13 +20,11 @@ package net.momirealms.customnameplates.object.requirements.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.HashMap;
public record PapiGreater(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
double value = Double.parseDouble(papiMap.get(papi));
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value > Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -20,13 +20,11 @@ package net.momirealms.customnameplates.object.requirements.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.HashMap;
public record PapiNoLarger(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
double value = Double.parseDouble(papiMap.get(papi));
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value <= Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -20,13 +20,11 @@ package net.momirealms.customnameplates.object.requirements.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.HashMap;
public record PapiNoLess(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
double value = Double.parseDouble(papiMap.get(papi));
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value >= Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -20,14 +20,13 @@ package net.momirealms.customnameplates.object.requirements.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Objects;
public record PapiNotEquals(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
String value = papiMap.get(papi);
public boolean isMet(Player player) {
String value = PlaceholderAPI.setPlaceholders(player, papi);
return !Objects.equals(value, PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -19,8 +19,6 @@ package net.momirealms.customnameplates.object.requirements.papi;
import org.bukkit.entity.Player;
import java.util.HashMap;
public interface PapiRequirement {
boolean isMet(HashMap<String, String> papiMap, Player player);
boolean isMet(Player player);
}

View File

@@ -20,13 +20,11 @@ package net.momirealms.customnameplates.object.requirements.papi;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.entity.Player;
import java.util.HashMap;
public record PapiSmaller(String papi, String requirement) implements PapiRequirement{
@Override
public boolean isMet(HashMap<String, String> papiMap, Player player) {
double value = Double.parseDouble(papiMap.get(papi));
public boolean isMet(Player player) {
double value = Double.parseDouble(PlaceholderAPI.setPlaceholders(player, papi));
return value < Double.parseDouble(PlaceholderAPI.setPlaceholders(player, requirement));
}
}

View File

@@ -19,8 +19,6 @@ package net.momirealms.customnameplates.utils;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.momirealms.customnameplates.CustomNameplates;
import org.bukkit.Bukkit;