+ * Copyright (C) Kristian S. Strangeland
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package xyz.ineanto.nicko.packet.wrapper;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.events.PacketContainer;
+import com.google.common.base.Objects;
+import org.bukkit.entity.Player;
+
+public abstract class AbstractPacket {
+ protected PacketContainer handle;
+
+ /**
+ * Constructs a new strongly typed wrapper for the given packet.
+ *
+ * @param handle - handle to the raw packet data.
+ * @param type - the packet type.
+ */
+ protected AbstractPacket(PacketContainer handle, PacketType type) {
+ // Make sure we're given a valid packet
+ if (handle == null)
+ throw new IllegalArgumentException("Packet handle cannot be NULL.");
+ if (!Objects.equal(handle.getType(), type))
+ throw new IllegalArgumentException(handle.getHandle()
+ + " is not a packet of type " + type);
+
+ this.handle = handle;
+ }
+
+ /**
+ * Retrieve a handle to the raw packet data.
+ *
+ * @return Raw packet data.
+ */
+ public PacketContainer getHandle() {
+ return handle;
+ }
+
+ /**
+ * Send the current packet to the given receiver.
+ *
+ * @param receiver - the receiver.
+ * @throws RuntimeException If the packet cannot be sent.
+ */
+ public void sendPacket(Player receiver) {
+ ProtocolLibrary.getProtocolManager().sendServerPacket(receiver,
+ getHandle());
+ }
+
+ /**
+ * Send the current packet to all online players.
+ */
+ public void broadcastPacket() {
+ ProtocolLibrary.getProtocolManager().broadcastServerPacket(getHandle());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerEntityDestroy.java b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerEntityDestroy.java
new file mode 100644
index 0000000..a23f1a6
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerEntityDestroy.java
@@ -0,0 +1,32 @@
+package xyz.ineanto.nicko.packet.wrapper;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.wrappers.Converters;
+import it.unimi.dsi.fastutil.ints.IntList;
+
+/**
+ * Sent by the server to the client to remove one or more entities.
+ */
+public class WrapperPlayServerEntityDestroy extends AbstractPacket {
+
+ /**
+ * The packet type that is wrapped by this wrapper.
+ */
+ public static final PacketType TYPE = PacketType.Play.Server.ENTITY_DESTROY;
+
+ public WrapperPlayServerEntityDestroy() {
+ super(new PacketContainer(TYPE), TYPE);
+ handle.getModifier().writeDefaults();
+ }
+
+ /**
+ * Sets the list of entity ids to remove
+ *
+ * @param value New value for field 'entityIds'
+ */
+ public void setEntityIds(IntList value) {
+ this.handle.getModifier().withType(IntList.class, Converters.passthrough(IntList.class)).writeSafely(0, value);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerRespawn.java b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerRespawn.java
new file mode 100644
index 0000000..f746450
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerRespawn.java
@@ -0,0 +1,147 @@
+package xyz.ineanto.nicko.packet.wrapper;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.InternalStructure;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.reflect.FuzzyReflection;
+import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.reflect.accessors.Accessors;
+import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
+import com.comphenix.protocol.utility.MinecraftReflection;
+import com.comphenix.protocol.utility.MinecraftVersion;
+import com.comphenix.protocol.wrappers.BukkitConverters;
+import com.comphenix.protocol.wrappers.EnumWrappers;
+import com.comphenix.protocol.wrappers.MinecraftKey;
+import com.google.common.hash.Hashing;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.World;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.RecordComponent;
+import java.util.Arrays;
+
+/**
+ * PacketPlayServerRespawn Wrapper class (1.20.X to 1.21.X)
+ *
+ * In 1.20.2, all the fields were merged inside a
+ * single "CommonPlayerSpawnInfo" record.
+ *
+ * @author inenato (w/ additional help from lukalt), based on work from dmulloy2 and Kristian S. Strangeland
+ */
+public class WrapperPlayServerRespawn extends AbstractPacket {
+ public static final PacketType TYPE = PacketType.Play.Server.RESPAWN;
+
+ private InternalStructure spawnInfoStructure = null;
+
+ public WrapperPlayServerRespawn() {
+ super(new PacketContainer(TYPE), TYPE);
+ handle.getModifier().writeDefaults();
+ if (MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove()) {
+ spawnInfoStructure = handle.getStructures().read(0);
+ }
+ }
+
+ public void setDimension(World value) {
+ final MinecraftVersion v1_20_5 = new MinecraftVersion(1, 20, 5);
+
+ if (!MinecraftVersion.getCurrentVersion().isAtLeast(v1_20_5)) {
+ // 1.20 - 1.20.4
+ final StructureModifier structureModifier = spawnInfoStructure == null ?
+ handle.getStructures() : spawnInfoStructure.getStructures();
+
+ final StructureModifier worldStructureModifier = spawnInfoStructure == null ?
+ handle.getWorldKeys() : spawnInfoStructure.getWorldKeys();
+
+ final InternalStructure dimensionType = structureModifier.read(0);
+ dimensionType.getMinecraftKeys().writeSafely(0, new MinecraftKey("minecraft", "dimension_type"));
+ dimensionType.getMinecraftKeys().writeSafely(1, new MinecraftKey("minecraft", "overworld"));
+ structureModifier.writeSafely(0, dimensionType);
+ worldStructureModifier.writeSafely(0, value);
+ } else {
+ // 1.20.5 to 1.21.1
+
+ try {
+ final Class> spawnInfoClass = MinecraftReflection.getMinecraftClass("network.protocol.game.CommonPlayerSpawnInfo");
+
+ Class>[] componentTypes = Arrays.stream(spawnInfoClass.getRecordComponents())
+ .map(RecordComponent::getType)
+ .toArray(Class>[]::new);
+ final Constructor> spawnInfoConstructor = spawnInfoClass.getDeclaredConstructor(componentTypes);
+
+ /**
+ * Holder dimensionType,
+ * ResourceKey dimension,
+ * long seed,
+ * GameType gameType,
+ * GameType previousGameType,
+ * boolean isDebug,
+ * boolean isFlat,
+ * Optional lastDeathLocation,
+ * int portalCooldown
+ */
+
+ final World world = Bukkit.getWorld("world");
+
+ FuzzyReflection.fromClass(spawnInfoClass).getConstructor(
+ FuzzyMethodContract
+ .newBuilder()
+ .build()
+ );
+
+ final Object spawnInfo = spawnInfoConstructor.newInstance(
+ BukkitConverters.getDimensionConverter().getGeneric(world),
+ BukkitConverters.getWorldKeyConverter().getGeneric(world),
+ world.getSeed(),
+ EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.NativeGameMode.fromBukkit(GameMode.SURVIVAL)),
+ EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.NativeGameMode.fromBukkit(GameMode.SURVIVAL)),
+ false,
+ false,
+ BukkitConverters.getSectionPositionConverter()
+ );
+
+ final Field commonSpawnDataField = Accessors.getFieldAccessor(TYPE.getPacketClass(), spawnInfoClass, true).getField();
+ commonSpawnDataField.set(spawnInfoStructure.getHandle(), spawnInfo);
+ } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException |
+ InstantiationException e) {
+ throw new RuntimeException();
+ }
+ }
+ }
+
+ public void setGameMode(GameMode value) {
+ if (!MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove()) {
+ // 1.20 to 1.20.1
+ handle.getGameModes().writeSafely(0, EnumWrappers.NativeGameMode.fromBukkit(value));
+ return;
+ }
+
+ spawnInfoStructure.getGameModes().writeSafely(0, EnumWrappers.NativeGameMode.fromBukkit(value));
+ }
+
+ public void setPreviousGameMode(GameMode value) {
+ if (!MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove()) {
+ // 1.20 to 1.20.1
+ handle.getGameModes().writeSafely(1, EnumWrappers.NativeGameMode.fromBukkit(value));
+ return;
+ }
+
+ spawnInfoStructure.getGameModes().writeSafely(1, EnumWrappers.NativeGameMode.fromBukkit(value));
+ }
+
+ public void setCopyMetadata(boolean value) {
+ if (!MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove()) return;
+
+ // 1.20 to 1.20.1
+ handle.getBooleans().writeSafely(0, value);
+ }
+
+ public void setSeed(long value) {
+ if (!MinecraftVersion.CONFIG_PHASE_PROTOCOL_UPDATE.atOrAbove()) {
+ // 1.20 to 1.20.1
+ handle.getLongs().writeSafely(0, Hashing.sha256().hashLong(value).asLong());
+ }
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerSpawnEntity.java b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerSpawnEntity.java
new file mode 100644
index 0000000..0512717
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayServerSpawnEntity.java
@@ -0,0 +1,103 @@
+package xyz.ineanto.nicko.packet.wrapper;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import org.bukkit.Location;
+import org.bukkit.entity.EntityType;
+
+import javax.annotation.Nonnull;
+import java.util.UUID;
+
+/**
+ * This packet is sent by the server when a player comes into visible range, not when a player joins.
+ */
+public class WrapperPlayServerSpawnEntity extends AbstractPacket {
+ /**
+ * The packet type that is wrapped by this wrapper.
+ */
+ public static final PacketType TYPE = PacketType.Play.Server.SPAWN_ENTITY;
+
+ /**
+ * Constructors a new wrapper for the specified packet
+ */
+ public WrapperPlayServerSpawnEntity() {
+ super(new PacketContainer(TYPE), TYPE);
+ handle.getModifier().writeDefaults();
+ }
+
+ /**
+ * Sets the entity id of the player
+ *
+ * @param value New value for field 'entityId'
+ */
+ public void setEntityId(int value) {
+ this.handle.getIntegers().writeSafely(0, value);
+ this.handle.getEntityTypeModifier().writeSafely(0, EntityType.PLAYER);
+ }
+
+ /**
+ * Sets the unique id of the player
+ *
+ * @param value New value for field 'playerId'
+ */
+ public void setPlayerId(UUID value) {
+ this.handle.getUUIDs().writeSafely(0, value);
+ }
+
+ /**
+ * Sets the value of field 'x'
+ *
+ * @param value New value for field 'x'
+ */
+ public void setX(double value) {
+ this.handle.getDoubles().writeSafely(0, value);
+ }
+
+ /**
+ * Sets the value of field 'y'
+ *
+ * @param value New value for field 'y'
+ */
+ public void setY(double value) {
+ this.handle.getDoubles().writeSafely(1, value);
+ }
+
+ /**
+ * Sets the value of field 'z'
+ *
+ * @param value New value for field 'z'
+ */
+ public void setZ(double value) {
+ this.handle.getDoubles().write(2, value);
+ }
+
+ /**
+ * Sets the discrete rotation around the y-axis (yaw)
+ *
+ * @param value New value for field 'yRot'
+ */
+ public void setYRotRaw(byte value) {
+ this.handle.getBytes().writeSafely(0, value);
+ }
+
+ /**
+ * Sets the discrete rotation around the x-axis (pitch)
+ *
+ * @param value New value for field 'xRot'
+ */
+ public void setXRotRaw(byte value) {
+ this.handle.getBytes().writeSafely(1, value);
+ }
+
+ public void setLocation(@Nonnull Location location) {
+ setX(location.getX());
+ setY(location.getY());
+ setZ(location.getZ());
+ setYRotRaw(degreesToAngle(location.getYaw()));
+ setXRotRaw(degreesToAngle(location.getPitch()));
+ }
+
+ private byte degreesToAngle(float degree) {
+ return (byte)((int)(degree * 256.0F / 360.0F));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayerServerPlayerInfo.java b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayerServerPlayerInfo.java
new file mode 100644
index 0000000..ca37dc0
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayerServerPlayerInfo.java
@@ -0,0 +1,37 @@
+package xyz.ineanto.nicko.packet.wrapper;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.utility.MinecraftVersion;
+import com.comphenix.protocol.wrappers.EnumWrappers;
+import com.comphenix.protocol.wrappers.PlayerInfoData;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Up-to-date version of the Wrapper class
+ * for the PlayerServerPlayerInfo.
+ *
+ * @author ineanto, based on work from dmulloy2 and Kristian S. Strangeland
+ */
+public class WrapperPlayerServerPlayerInfo extends AbstractPacket {
+ public static final PacketType TYPE = PacketType.Play.Server.PLAYER_INFO;
+
+ public WrapperPlayerServerPlayerInfo() {
+ super(new PacketContainer(TYPE), TYPE);
+ handle.getModifier().writeDefaults();
+ }
+
+ public void setActions(Set value) {
+ if (MinecraftVersion.FEATURE_PREVIEW_UPDATE.atOrAbove()) {
+ handle.getPlayerInfoActions().writeSafely(0, value);
+ } else {
+ handle.getPlayerInfoAction().writeSafely(0, value.stream().iterator().next()); // Get the first Value.
+ }
+ }
+
+ public void setData(List value) {
+ handle.getPlayerInfoDataLists().writeSafely(1, value);
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayerServerPlayerInfoRemove.java b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayerServerPlayerInfoRemove.java
new file mode 100644
index 0000000..2273c48
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/packet/wrapper/WrapperPlayerServerPlayerInfoRemove.java
@@ -0,0 +1,27 @@
+package xyz.ineanto.nicko.packet.wrapper;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.events.PacketContainer;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Up-to-date version of the Wrapper class
+ * for the PlayerServerPlayerInfoRemove.
+ *
+ * @author ineanto, based on work from dmulloy2 and Kristian S. Strangeland
+ */
+
+public class WrapperPlayerServerPlayerInfoRemove extends AbstractPacket {
+ public static final PacketType TYPE = PacketType.Play.Server.PLAYER_INFO_REMOVE;
+
+ public WrapperPlayerServerPlayerInfoRemove() {
+ super(new PacketContainer(TYPE), TYPE);
+ handle.getModifier().writeDefaults();
+ }
+
+ public void setUUIDs(List value) {
+ handle.getUUIDLists().writeSafely(0, value);
+ }
+}
diff --git a/core/src/main/java/net/artelnatif/nicko/placeholder/NickoExpansion.java b/src/main/java/xyz/ineanto/nicko/placeholder/NickoExpansion.java
similarity index 59%
rename from core/src/main/java/net/artelnatif/nicko/placeholder/NickoExpansion.java
rename to src/main/java/xyz/ineanto/nicko/placeholder/NickoExpansion.java
index 7f3e39d..b51455a 100644
--- a/core/src/main/java/net/artelnatif/nicko/placeholder/NickoExpansion.java
+++ b/src/main/java/xyz/ineanto/nicko/placeholder/NickoExpansion.java
@@ -1,19 +1,19 @@
-package net.artelnatif.nicko.placeholder;
+package xyz.ineanto.nicko.placeholder;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.NickoProfile;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import xyz.ineanto.nicko.Nicko;
+import xyz.ineanto.nicko.profile.NickoProfile;
import java.util.Optional;
public class NickoExpansion extends PlaceholderExpansion {
- private final NickoBukkit instance;
+ private final Nicko instance;
- public NickoExpansion(NickoBukkit instance) {
+ public NickoExpansion(Nicko instance) {
this.instance = instance;
}
@@ -24,12 +24,12 @@ public class NickoExpansion extends PlaceholderExpansion {
@Override
public @NotNull String getAuthor() {
- return "Aro";
+ return "Ineanto";
}
@Override
public @NotNull String getVersion() {
- return "1.0.0";
+ return "1.0.1";
}
@Override
@@ -42,29 +42,27 @@ public class NickoExpansion extends PlaceholderExpansion {
if (player == null) return null;
String name, skin, locale;
- boolean bungeecord;
+ boolean randomSkin;
name = skin = player.getName();
locale = "N/A";
- bungeecord = true;
+ randomSkin = false;
final Optional optionalProfile = instance.getDataStore().getData(player.getUniqueId());
if (optionalProfile.isPresent()) {
final NickoProfile profile = optionalProfile.get();
- if (!profile.isEmpty()) {
- name = profile.getName();
- skin = profile.getSkin();
- }
+ name = profile.getName() == null ? player.getName() : profile.getName();
+ skin = profile.getSkin() == null ? player.getName() : profile.getSkin();
locale = profile.getLocale().getName();
- bungeecord = profile.isBungeecordTransfer();
+ randomSkin = profile.isRandomSkin();
}
- switch (params) {
- case "name": return name;
- case "skin": return skin;
- case "locale": return locale;
- case "bungeecord": return String.valueOf(bungeecord);
- default: return null;
- }
+ return switch (params) {
+ case "name" -> name;
+ case "skin" -> skin;
+ case "locale" -> locale;
+ case "random_skin" -> String.valueOf(randomSkin);
+ default -> null;
+ };
}
}
diff --git a/src/main/java/xyz/ineanto/nicko/profile/NickoProfile.java b/src/main/java/xyz/ineanto/nicko/profile/NickoProfile.java
new file mode 100644
index 0000000..b1a78bb
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/profile/NickoProfile.java
@@ -0,0 +1,103 @@
+package xyz.ineanto.nicko.profile;
+
+import org.bukkit.entity.Player;
+import xyz.ineanto.nicko.Nicko;
+import xyz.ineanto.nicko.appearance.Appearance;
+import xyz.ineanto.nicko.language.Language;
+import xyz.ineanto.nicko.storage.PlayerDataStore;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+public class NickoProfile implements Cloneable {
+ public static final NickoProfile EMPTY_PROFILE = new NickoProfile(
+ new Appearance(null, null),
+ Language.ENGLISH,
+ true,
+ Collections.emptyList()
+ );
+
+ private static final Nicko instance = Nicko.getInstance();
+ private static final PlayerDataStore dataStore = instance.getDataStore();
+
+ private Appearance appearance;
+ private Language language;
+ private boolean randomSkin;
+ private List favorites;
+
+ public NickoProfile(Appearance appearance, Language language, boolean randomSkin, List favorites) {
+ this.appearance = appearance;
+ this.language = language;
+ this.randomSkin = randomSkin;
+ this.favorites = favorites;
+ }
+
+ public static Optional get(Player player) {
+ return dataStore.getData(player.getUniqueId());
+ }
+
+ public static Optional get(UUID uuid) {
+ return dataStore.getData(uuid);
+ }
+
+ public Appearance getAppearance() {
+ return appearance;
+ }
+
+ public boolean hasData() {
+ return appearance.name() != null || appearance.skin() != null;
+ }
+
+ public String getName() {
+ return appearance.name();
+ }
+
+ public void setName(String name) {
+ this.appearance = new Appearance(name, appearance.skin() == null ? null : appearance.skin());
+ }
+
+ public String getSkin() {
+ return appearance.skin();
+ }
+
+ public void setSkin(String skin) {
+ this.appearance = new Appearance(appearance.name() == null ? null : appearance.name(), skin);
+ }
+
+ public List getFavorites() {
+ return favorites;
+ }
+
+ public void setFavorites(List favorites) {
+ this.favorites = favorites;
+ }
+
+ public Language getLocale() {
+ return language;
+ }
+
+ public void setLocale(Language language) {
+ this.language = language;
+ }
+
+ public boolean isRandomSkin() {
+ return randomSkin;
+ }
+
+ public void setRandomSkin(boolean randomSkin) {
+ this.randomSkin = randomSkin;
+ }
+
+ @Override
+ public NickoProfile clone() {
+ Object o;
+ try {
+ o = super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ return (NickoProfile) o;
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/prompt/Prompt.java b/src/main/java/xyz/ineanto/nicko/prompt/Prompt.java
new file mode 100644
index 0000000..5940993
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/prompt/Prompt.java
@@ -0,0 +1,63 @@
+package xyz.ineanto.nicko.prompt;
+
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import xyz.ineanto.nicko.Nicko;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.appearance.AppearanceManager;
+import xyz.ineanto.nicko.language.LanguageKey;
+import xyz.ineanto.nicko.language.PlayerLanguage;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.PlayerDataStore;
+
+import javax.annotation.Nullable;
+import java.util.Optional;
+
+public abstract class Prompt {
+ private final Player player;
+ private final AppearanceManager appearanceManager;
+ private final NickoProfile profile;
+ private final PlayerDataStore dataStore = Nicko.getInstance().getDataStore();
+
+ protected final PlayerLanguage playerLanguage;
+
+ public Prompt(Player player) {
+ this.player = player;
+ this.appearanceManager = new AppearanceManager(player);
+ this.playerLanguage = new PlayerLanguage(player);
+
+ final Optional optionalProfile = dataStore.getData(player.getUniqueId());
+ this.profile = optionalProfile.orElse(NickoProfile.EMPTY_PROFILE.clone());
+ }
+
+ public abstract void displayNameThenSkinPrompt();
+
+ public abstract void displaySkinPrompt();
+
+ public abstract void displayNamePrompt();
+
+ public void update(@Nullable String name, @Nullable String skin, boolean skinChange) {
+ if (name != null && !name.isBlank()) {
+ profile.setName(name);
+ }
+
+ if (skin != null && !skin.isBlank()) {
+ profile.setSkin(skin);
+ }
+
+ dataStore.updateCache(player.getUniqueId(), profile);
+
+ final ActionResult actionResult = appearanceManager.update(skinChange);
+ if (!actionResult.isError()) {
+ player.sendMessage(playerLanguage.translateWithWhoosh(LanguageKey.Event.Appearance.Set.OK));
+ player.playSound(player.getLocation(), Sound.BLOCK_WOODEN_BUTTON_CLICK_ON, 1f, 1f);
+ } else {
+ player.sendMessage(
+ playerLanguage.translateWithOops(
+ LanguageKey.Event.Appearance.Set.ERROR,
+ playerLanguage.translate(actionResult.getErrorKey(), false)
+ ));
+ player.playSound(player.getLocation(), Sound.BLOCK_ANVIL_PLACE, 1f, 1f);
+ }
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/prompt/PromptManager.java b/src/main/java/xyz/ineanto/nicko/prompt/PromptManager.java
new file mode 100644
index 0000000..bbd5a9e
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/prompt/PromptManager.java
@@ -0,0 +1,24 @@
+package xyz.ineanto.nicko.prompt;
+
+import org.bukkit.entity.Player;
+import xyz.ineanto.nicko.prompt.conversation.ConversationPrompt;
+
+public class PromptManager {
+ private final Prompt prompt;
+
+ public PromptManager(Player player) {
+ this.prompt = new ConversationPrompt(player);
+ }
+
+ public void displayNameThenSkinPrompt() {
+ prompt.displayNameThenSkinPrompt();
+ }
+
+ public void displaySkinPrompt() {
+ prompt.displaySkinPrompt();
+ }
+
+ public void displayNamePromptThenUpdate() {
+ prompt.displayNamePrompt();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/xyz/ineanto/nicko/prompt/anvil/AnvilPrompt.java b/src/main/java/xyz/ineanto/nicko/prompt/anvil/AnvilPrompt.java
new file mode 100644
index 0000000..85e6d28
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/prompt/anvil/AnvilPrompt.java
@@ -0,0 +1,105 @@
+package xyz.ineanto.nicko.prompt.anvil;
+
+import net.kyori.adventure.text.Component;
+import net.wesjd.anvilgui.AnvilGUI;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import xyz.ineanto.nicko.Nicko;
+import xyz.ineanto.nicko.prompt.Prompt;
+import xyz.ineanto.nicko.language.LanguageKey;
+import xyz.ineanto.nicko.mojang.MojangUtils;
+
+import java.util.Collections;
+
+/**
+ * This is currently unused, I'm waiting on AnvilGUI
+ * to be compiled against Paper mappings.
+ */
+// TODO (Ineanto, 16/05/2025): Do some validation on the inputs
+public class AnvilPrompt extends Prompt {
+ private final Player player;
+
+ private String name;
+ private String skin;
+
+ public AnvilPrompt(Player player) {
+ super(player);
+ this.player = player;
+ }
+
+ @Override
+ public void displayNameThenSkinPrompt() {
+ new AnvilGUI.Builder()
+ .plugin(Nicko.getInstance())
+ .itemLeft(getLeftItem(false))
+ .interactableSlots(AnvilGUI.Slot.OUTPUT)
+ .onClick((slot, snapshot) -> {
+ if (slot == AnvilGUI.Slot.OUTPUT) {
+ if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
+ return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
+ } else {
+ // Praying that it works. This is untested code!
+ name = snapshot.getText();
+ displaySkinPrompt();
+ }
+ }
+ return Collections.emptyList();
+ })
+ .text("New name...").open(player);
+ }
+
+ @Override
+ public void displaySkinPrompt() {
+ new AnvilGUI.Builder()
+ .plugin(Nicko.getInstance())
+ .itemLeft(getLeftItem(true))
+ .interactableSlots(AnvilGUI.Slot.OUTPUT)
+ .onClick((slot, snapshot) -> {
+ if (slot == AnvilGUI.Slot.OUTPUT) {
+ if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
+ return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
+ } else {
+ skin = snapshot.getText();
+ update(name == null ? null : name, skin, true);
+ return Collections.singletonList(AnvilGUI.ResponseAction.close());
+ }
+ }
+ return Collections.emptyList();
+ })
+ .text("New skin...").open(player);
+ }
+
+ @Override
+ public void displayNamePrompt() {
+ new AnvilGUI.Builder()
+ .plugin(Nicko.getInstance())
+ .itemLeft(getLeftItem(false))
+ .interactableSlots(AnvilGUI.Slot.OUTPUT)
+ .onClick((slot, snapshot) -> {
+ if (slot == AnvilGUI.Slot.OUTPUT) {
+ if (MojangUtils.isUsernameInvalid(snapshot.getText())) {
+ return Collections.singletonList(AnvilGUI.ResponseAction.replaceInputText("Invalid username!"));
+ } else {
+ update(snapshot.getText(), null, false);
+ return Collections.singletonList(AnvilGUI.ResponseAction.close());
+ }
+ }
+ return Collections.emptyList();
+ })
+ .text("New name...").open(player);
+ }
+
+ private ItemStack getLeftItem(boolean skin) {
+ final ItemStack item = new ItemStack(Material.PAPER);
+ final ItemMeta meta = item.getItemMeta();
+
+ if (meta != null) {
+ meta.displayName(Component.text(playerLanguage.translate(skin ? LanguageKey.GUI.NEW_SKIN : LanguageKey.GUI.NEW_NAME, false)));
+ }
+
+ item.setItemMeta(meta);
+ return item;
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/prompt/conversation/ConversationPrompt.java b/src/main/java/xyz/ineanto/nicko/prompt/conversation/ConversationPrompt.java
new file mode 100644
index 0000000..701ce6c
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/prompt/conversation/ConversationPrompt.java
@@ -0,0 +1,89 @@
+package xyz.ineanto.nicko.prompt.conversation;
+
+import org.bukkit.conversations.ConversationContext;
+import org.bukkit.conversations.ConversationFactory;
+import org.bukkit.conversations.StringPrompt;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import xyz.ineanto.nicko.Nicko;
+import xyz.ineanto.nicko.prompt.Prompt;
+import xyz.ineanto.nicko.language.LanguageKey;
+
+import java.util.Map;
+import java.util.Objects;
+
+public class ConversationPrompt extends Prompt {
+ private final String changeBothTag = "changeBoth";
+ private final Player player;
+ private final ConversationFactory conversationFactory = new ConversationFactory(Nicko.getInstance())
+ .withTimeout(30)
+ .withModality(false)
+ .withEscapeSequence("EXIT")
+ .withLocalEcho(false)
+ .thatExcludesNonPlayersWithMessage("Player only");
+
+ private String name;
+
+ public ConversationPrompt(Player player) {
+ super(player);
+ this.player = player;
+ }
+
+ @Override
+ public void displayNameThenSkinPrompt() {
+ conversationFactory
+ .withFirstPrompt(new ChangeNameConversation())
+ .withInitialSessionData(Map.of(changeBothTag, true))
+ .buildConversation(player)
+ .begin();
+ }
+
+ @Override
+ public void displaySkinPrompt() {
+ conversationFactory
+ .withFirstPrompt(new ChangeSkinConversation())
+ .buildConversation(player)
+ .begin();
+ }
+
+ @Override
+ public void displayNamePrompt() {
+ conversationFactory
+ .withFirstPrompt(new ChangeNameConversation())
+ .buildConversation(player)
+ .begin();
+ }
+
+ private class ChangeNameConversation extends StringPrompt {
+ @Override
+ public @NotNull String getPromptText(@NotNull ConversationContext context) {
+ return playerLanguage.translate(LanguageKey.Event.Appearance.Set.CHAT_PROMPT_NAME, true);
+ }
+
+ @Override
+ public @Nullable org.bukkit.conversations.Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input) {
+ if (Objects.equals(context.getSessionData(changeBothTag), true)) {
+ name = input;
+ return new ChangeSkinConversation();
+ }
+
+ update(input, null, false);
+ return END_OF_CONVERSATION;
+ }
+ }
+
+ private class ChangeSkinConversation extends StringPrompt {
+ @Override
+ public @NotNull String getPromptText(@NotNull ConversationContext context) {
+ return playerLanguage.translate(LanguageKey.Event.Appearance.Set.CHAT_PROMPT_SKIN, true);
+ }
+
+ @Override
+ public @Nullable org.bukkit.conversations.Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input) {
+ update(name != null ? name : null, input, true);
+ name = null;
+ return END_OF_CONVERSATION;
+ }
+ }
+}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/cache/Cache.java b/src/main/java/xyz/ineanto/nicko/storage/Cache.java
similarity index 62%
rename from core/src/main/java/net/artelnatif/nicko/storage/cache/Cache.java
rename to src/main/java/xyz/ineanto/nicko/storage/Cache.java
index 92d5b75..1b2616d 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/cache/Cache.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/Cache.java
@@ -1,7 +1,7 @@
-package net.artelnatif.nicko.storage.cache;
+package xyz.ineanto.nicko.storage;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.profile.NickoProfile;
import java.util.Optional;
import java.util.UUID;
@@ -11,12 +11,14 @@ public abstract class Cache {
public abstract CacheProvider getProvider();
- public abstract ActionResult cache(UUID uuid, NickoProfile profile);
+ public abstract ActionResult cache(UUID uuid, NickoProfile profile);
public abstract boolean isCached(UUID uuid);
public abstract Optional retrieve(UUID uuid);
+ public abstract ActionResult delete(UUID uuid);
+
public boolean isError() {
return error;
}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/cache/CacheProvider.java b/src/main/java/xyz/ineanto/nicko/storage/CacheProvider.java
similarity index 63%
rename from core/src/main/java/net/artelnatif/nicko/storage/cache/CacheProvider.java
rename to src/main/java/xyz/ineanto/nicko/storage/CacheProvider.java
index e85fd3a..3597ac5 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/cache/CacheProvider.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/CacheProvider.java
@@ -1,4 +1,4 @@
-package net.artelnatif.nicko.storage.cache;
+package xyz.ineanto.nicko.storage;
public interface CacheProvider {
boolean init();
diff --git a/src/main/java/xyz/ineanto/nicko/storage/PlayerDataStore.java b/src/main/java/xyz/ineanto/nicko/storage/PlayerDataStore.java
new file mode 100644
index 0000000..2ba648f
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/PlayerDataStore.java
@@ -0,0 +1,106 @@
+package xyz.ineanto.nicko.storage;
+
+import org.bukkit.entity.Player;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.language.LanguageKey;
+import xyz.ineanto.nicko.mojang.MojangAPI;
+import xyz.ineanto.nicko.mojang.MojangUtils;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.json.JSONStorage;
+import xyz.ineanto.nicko.storage.map.MapCache;
+import xyz.ineanto.nicko.storage.mariadb.MariaDBStorage;
+import xyz.ineanto.nicko.storage.mysql.MySQLStorage;
+import xyz.ineanto.nicko.storage.redis.RedisCache;
+
+import java.io.IOException;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+
+public class PlayerDataStore {
+ private final MojangAPI mojangAPI;
+
+ private Storage storage;
+ private Cache cache;
+
+ public PlayerDataStore(MojangAPI mojangAPI, Configuration configuration) {
+ this.mojangAPI = mojangAPI;
+ this.storage = configuration.getSqlConfiguration().isEnabled() ?
+ configuration.getSqlConfiguration().isMariadb() ? new MariaDBStorage(configuration) : new MySQLStorage(configuration)
+ : new JSONStorage();
+ this.cache = configuration.getRedisConfiguration().isEnabled() ? new RedisCache(configuration) : new MapCache();
+ }
+
+ public ActionResult updateCache(UUID uuid, NickoProfile profile) {
+ if (storage.isError() || cache.isError()) {
+ return ActionResult.error(LanguageKey.Error.CACHE);
+ }
+
+ getCache().cache(uuid, profile);
+ return ActionResult.ok();
+ }
+
+ public Optional getData(UUID uuid) {
+ if (storage.isError() || cache.isError()) {
+ return Optional.empty();
+ }
+
+ if (cache.isCached(uuid)) {
+ return cache.retrieve(uuid);
+ } else if (storage.isStored(uuid)) {
+ final Optional retrievedProfile = storage.retrieve(uuid);
+ retrievedProfile.ifPresent(profile -> cache.cache(uuid, profile));
+ return retrievedProfile;
+ } else {
+ final NickoProfile newProfile = NickoProfile.EMPTY_PROFILE.clone();
+ cache.cache(uuid, newProfile);
+ return Optional.of(newProfile);
+ }
+ }
+
+ public Optional getOfflineData(String name) {
+ if (storage.isError() || cache.isError()) {
+ return Optional.empty();
+ }
+
+ try {
+ final Optional uuidTrimmed = mojangAPI.getUUID(name);
+ if (uuidTrimmed.isPresent()) {
+ final UUID uuid = MojangUtils.fromTrimmed(uuidTrimmed.get());
+ return getData(uuid);
+ }
+ return Optional.empty();
+ } catch (IOException | ExecutionException e) {
+ return Optional.empty();
+ }
+ }
+
+ public ActionResult saveData(Player player) {
+ if (storage.isError()) return ActionResult.error();
+ if (cache.isError()) return ActionResult.error();
+ if (!cache.isCached(player.getUniqueId())) return ActionResult.error();
+
+ final Optional cachedProfile = cache.retrieve(player.getUniqueId());
+ if (cachedProfile.isEmpty()) return ActionResult.error();
+
+ cache.delete(player.getUniqueId());
+ return storage.store(player.getUniqueId(), cachedProfile.get());
+ }
+
+ public Storage getStorage() {
+ return storage;
+ }
+
+ public void setStorage(Storage storage) {
+ this.storage = storage;
+ }
+
+ public Cache getCache() {
+ return cache;
+ }
+
+ public void setCache(Cache cache) {
+ this.cache = cache;
+ }
+}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/Storage.java b/src/main/java/xyz/ineanto/nicko/storage/Storage.java
similarity index 62%
rename from core/src/main/java/net/artelnatif/nicko/storage/Storage.java
rename to src/main/java/xyz/ineanto/nicko/storage/Storage.java
index b23b1ef..9cac04a 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/Storage.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/Storage.java
@@ -1,7 +1,7 @@
-package net.artelnatif.nicko.storage;
+package xyz.ineanto.nicko.storage;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.profile.NickoProfile;
import java.util.Optional;
import java.util.UUID;
@@ -11,12 +11,14 @@ public abstract class Storage {
public abstract StorageProvider getProvider();
- public abstract ActionResult store(UUID uuid, NickoProfile profile);
+ public abstract ActionResult store(UUID uuid, NickoProfile profile);
public abstract boolean isStored(UUID uuid);
public abstract Optional retrieve(UUID uuid);
+ public abstract ActionResult delete(UUID uuid);
+
public boolean isError() {
return error;
}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/StorageProvider.java b/src/main/java/xyz/ineanto/nicko/storage/StorageProvider.java
similarity index 67%
rename from core/src/main/java/net/artelnatif/nicko/storage/StorageProvider.java
rename to src/main/java/xyz/ineanto/nicko/storage/StorageProvider.java
index 41b66de..3981771 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/StorageProvider.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/StorageProvider.java
@@ -1,4 +1,4 @@
-package net.artelnatif.nicko.storage;
+package xyz.ineanto.nicko.storage;
public interface StorageProvider {
boolean init();
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/json/JSONStorage.java b/src/main/java/xyz/ineanto/nicko/storage/json/JSONStorage.java
similarity index 67%
rename from core/src/main/java/net/artelnatif/nicko/storage/json/JSONStorage.java
rename to src/main/java/xyz/ineanto/nicko/storage/json/JSONStorage.java
index a0f6846..cf7a15c 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/json/JSONStorage.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/json/JSONStorage.java
@@ -1,13 +1,12 @@
-package net.artelnatif.nicko.storage.json;
+package xyz.ineanto.nicko.storage.json;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.i18n.I18NDict;
-import net.artelnatif.nicko.storage.Storage;
-import net.artelnatif.nicko.storage.StorageProvider;
+import xyz.ineanto.nicko.Nicko;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.Storage;
+import xyz.ineanto.nicko.storage.StorageProvider;
import java.io.*;
import java.util.Optional;
@@ -17,7 +16,7 @@ import java.util.logging.Logger;
public class JSONStorage extends Storage {
private final Logger logger = Logger.getLogger("JSONStorage");
private final Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
- private final File directory = new File(NickoBukkit.getInstance().getDataFolder() + "/players/");
+ private final File directory = new File(Nicko.getInstance().getDataFolder() + "/players/");
private JSONStorageProvider provider;
@@ -30,7 +29,7 @@ public class JSONStorage extends Storage {
}
@Override
- public ActionResult store(UUID uuid, NickoProfile profile) {
+ public ActionResult store(UUID uuid, NickoProfile profile) {
final String profileToJson = gson.toJson(profile);
final File file = new File(directory, uuid.toString() + ".json");
@@ -42,27 +41,26 @@ public class JSONStorage extends Storage {
}
} catch (IOException e) {
logger.warning("Could not write to file.");
- return new ActionResult<>(I18NDict.Error.JSON_ERROR);
+ return ActionResult.error();
}
}
} catch (IOException e) {
logger.warning("Could not create file.");
- return new ActionResult<>(I18NDict.Error.JSON_ERROR);
+ e.printStackTrace();
+ return ActionResult.error();
}
- return new ActionResult<>();
+ return ActionResult.ok();
}
@Override
public boolean isStored(UUID uuid) {
- final File directory = new File(NickoBukkit.getInstance().getDataFolder() + "/players/");
final File file = new File(directory, uuid.toString() + ".json");
return file.exists();
}
@Override
public Optional retrieve(UUID uuid) {
- final File directory = new File(NickoBukkit.getInstance().getDataFolder() + "/players/");
final File file = new File(directory, uuid.toString() + ".json");
try (FileReader fileReader = new FileReader(file)) {
try (BufferedReader reader = new BufferedReader(fileReader)) {
@@ -74,7 +72,21 @@ public class JSONStorage extends Storage {
}
}
+ @Override
+ public ActionResult delete(UUID uuid) {
+ final File file = new File(directory, uuid.toString() + ".json");
+ if (file.delete() || !file.exists()) {
+ return ActionResult.ok();
+ }
+ return ActionResult.error();
+ }
+
private boolean checkFileExists(File file) throws IOException {
+ // Additional check if the folder gets deleted while the plugin is running.
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+
if (!file.exists()) {
return file.createNewFile();
}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/json/JSONStorageProvider.java b/src/main/java/xyz/ineanto/nicko/storage/json/JSONStorageProvider.java
similarity index 63%
rename from core/src/main/java/net/artelnatif/nicko/storage/json/JSONStorageProvider.java
rename to src/main/java/xyz/ineanto/nicko/storage/json/JSONStorageProvider.java
index ac2be77..e360b6f 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/json/JSONStorageProvider.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/json/JSONStorageProvider.java
@@ -1,6 +1,6 @@
-package net.artelnatif.nicko.storage.json;
+package xyz.ineanto.nicko.storage.json;
-import net.artelnatif.nicko.storage.StorageProvider;
+import xyz.ineanto.nicko.storage.StorageProvider;
import java.io.File;
@@ -12,11 +12,12 @@ public class JSONStorageProvider implements StorageProvider {
}
@Override
- public boolean init()
- {
+ public boolean init() {
return directory.exists() || directory.mkdirs();
}
@Override
- public boolean close() { return true; }
+ public boolean close() {
+ return true;
+ }
}
diff --git a/src/main/java/xyz/ineanto/nicko/storage/map/MapCache.java b/src/main/java/xyz/ineanto/nicko/storage/map/MapCache.java
new file mode 100644
index 0000000..ebc3a88
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/map/MapCache.java
@@ -0,0 +1,51 @@
+package xyz.ineanto.nicko.storage.map;
+
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.Cache;
+import xyz.ineanto.nicko.storage.CacheProvider;
+
+import java.util.HashMap;
+import java.util.Optional;
+import java.util.UUID;
+
+public class MapCache extends Cache {
+ private MapCacheProvider provider;
+
+ @Override
+ public CacheProvider getProvider() {
+ if (provider == null) {
+ provider = new MapCacheProvider();
+ }
+ return provider;
+ }
+
+ @Override
+ public ActionResult cache(UUID uuid, NickoProfile profile) {
+ final HashMap profiles = provider.getMap();
+ profiles.put(uuid, profile);
+ return ActionResult.ok();
+ }
+
+ @Override
+ public boolean isCached(UUID uuid) {
+ final HashMap profiles = provider.getMap();
+ return profiles.containsKey(uuid);
+ }
+
+ @Override
+ public Optional retrieve(UUID uuid) {
+ final HashMap profiles = provider.getMap();
+ if (isCached(uuid)) {
+ return Optional.of(profiles.get(uuid));
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public ActionResult delete(UUID uuid) {
+ final HashMap profiles = provider.getMap();
+ profiles.remove(uuid);
+ return ActionResult.ok();
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/storage/map/MapCacheProvider.java b/src/main/java/xyz/ineanto/nicko/storage/map/MapCacheProvider.java
new file mode 100644
index 0000000..bfb85bd
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/map/MapCacheProvider.java
@@ -0,0 +1,28 @@
+package xyz.ineanto.nicko.storage.map;
+
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.CacheProvider;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+public class MapCacheProvider implements CacheProvider {
+ private HashMap profiles;
+
+ @Override
+ public boolean init() {
+ if (profiles == null) {
+ profiles = new HashMap<>();
+ }
+ return true;
+ }
+
+ @Override
+ public boolean close() {
+ return true;
+ }
+
+ public HashMap getMap() {
+ return profiles;
+ }
+}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java b/src/main/java/xyz/ineanto/nicko/storage/mariadb/MariaDBStorage.java
similarity index 54%
rename from core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java
rename to src/main/java/xyz/ineanto/nicko/storage/mariadb/MariaDBStorage.java
index 8dcea73..6bc9c43 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorage.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/mariadb/MariaDBStorage.java
@@ -1,53 +1,57 @@
-package net.artelnatif.nicko.storage.sql;
+package xyz.ineanto.nicko.storage.mariadb;
-import net.artelnatif.nicko.config.Configuration;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.i18n.I18NDict;
-import net.artelnatif.nicko.i18n.Locale;
-import net.artelnatif.nicko.storage.Storage;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.appearance.Appearance;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.language.Language;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.Storage;
-import java.io.ByteArrayInputStream;
-import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.logging.Logger;
-public class SQLStorage extends Storage {
+public class MariaDBStorage extends Storage {
private final Logger logger = Logger.getLogger("SQLStorage");
private final Configuration configuration;
+ private final Gson gson = new GsonBuilder().serializeNulls().create();
- private SQLStorageProvider provider;
+ private MariaDBStorageProvider provider;
- public SQLStorage(Configuration configuration) {
+ public MariaDBStorage(Configuration configuration) {
this.configuration = configuration;
}
@Override
- public SQLStorageProvider getProvider() {
+ public MariaDBStorageProvider getProvider() {
if (provider == null) {
- provider = new SQLStorageProvider(configuration);
+ provider = new MariaDBStorageProvider(configuration);
}
return provider;
}
@Override
- public ActionResult store(UUID uuid, NickoProfile profile) {
+ public ActionResult store(UUID uuid, NickoProfile profile) {
final Connection connection = getProvider().getConnection();
- if (connection == null) return new ActionResult<>(I18NDict.Error.SQL_ERROR);
+ if (connection == null) return ActionResult.error();
try {
final PreparedStatement statement = isStored(uuid) ?
getUpdateStatement(connection, uuid, profile) : getInsertStatement(connection, uuid, profile);
statement.executeUpdate();
- return new ActionResult<>();
+ return ActionResult.ok();
} catch (SQLException e) {
logger.warning("Couldn't send SQL Request: " + e.getMessage());
- return new ActionResult<>(I18NDict.Error.SQL_ERROR);
+ return ActionResult.error();
}
}
@@ -57,10 +61,10 @@ public class SQLStorage extends Storage {
if (connection == null) return false;
try {
- final String sql = "SELECT * FROM nicko.DATA WHERE uuid = ?";
+ final String sql = "SELECT uuid FROM nicko.DATA WHERE uuid = ?";
final PreparedStatement statement = connection.prepareStatement(sql);
- statement.setBinaryStream(1, uuidToBin(uuid));
+ statement.setString(1, uuid.toString());
final ResultSet resultSet = statement.executeQuery();
return resultSet.next();
@@ -74,26 +78,29 @@ public class SQLStorage extends Storage {
public Optional retrieve(UUID uuid) {
final Connection connection = getProvider().getConnection();
if (connection == null) return Optional.empty();
+ if (!isStored(uuid)) return Optional.empty();
try {
final String sql = "SELECT * FROM nicko.DATA WHERE uuid = ?";
final PreparedStatement statement = connection.prepareStatement(sql);
- statement.setBinaryStream(1, uuidToBin(uuid));
+ statement.setString(1, uuid.toString());
final ResultSet resultSet = statement.executeQuery();
String name = "";
String skin = "";
String locale = "";
- boolean bungeecord = false;
+ boolean randomSkin = false;
+ List favorites = Collections.emptyList();
while (resultSet.next()) {
name = resultSet.getString("name");
skin = resultSet.getString("skin");
locale = resultSet.getString("locale");
- bungeecord = resultSet.getBoolean("bungeecord");
+ randomSkin = resultSet.getBoolean("randomskin");
+ favorites = gson.fromJson(resultSet.getString("favorites"), new TypeToken>() { }.getType());
}
- final NickoProfile profile = new NickoProfile(name, skin, Locale.fromCode(locale), bungeecord);
+ final NickoProfile profile = new NickoProfile(new Appearance(name, skin), Language.fromCode(locale), randomSkin, favorites);
return Optional.of(profile);
} catch (SQLException e) {
logger.warning("Couldn't fetch profile: " + e.getMessage());
@@ -101,33 +108,43 @@ public class SQLStorage extends Storage {
}
}
+ @Override
+ public ActionResult delete(UUID uuid) {
+ final Connection connection = getProvider().getConnection();
+ if (connection == null) return ActionResult.error();
+
+ try {
+ final String sql = "DELETE FROM nicko.DATA WHERE uuid = ?";
+ final PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setString(1, uuid.toString());
+ int rows = statement.executeUpdate();
+ return (rows == 1 ? ActionResult.ok() : ActionResult.error());
+ } catch (SQLException e) {
+ logger.warning("Couldn't delete profile: " + e.getMessage());
+ return ActionResult.error();
+ }
+ }
+
private PreparedStatement getInsertStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
- final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `bungeecord`) VALUES (?, ?, ?, ?, ?)";
+ final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `randomskin`, `favorites`) VALUES (?, ?, ?, ?, ?, ?)";
final PreparedStatement statement = connection.prepareStatement(sql);
- statement.setBinaryStream(1, uuidToBin(uuid));
+ statement.setString(1, uuid.toString());
statement.setString(2, profile.getName() == null ? null : profile.getName());
statement.setString(3, profile.getSkin() == null ? null : profile.getSkin());
statement.setString(4, profile.getLocale().getCode());
- statement.setBoolean(5, profile.isBungeecordTransfer());
+ statement.setBoolean(5, profile.isRandomSkin());
+ statement.setString(6, gson.toJson(profile.getFavorites(), new TypeToken>() { }.getRawType()));
return statement;
}
private PreparedStatement getUpdateStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
- final String sql = "UPDATE nicko.DATA SET name = ?, skin = ?, locale = ?, bungeecord = ? WHERE uuid = ?";
+ final String sql = "UPDATE nicko.DATA SET name = ?, skin = ?, locale = ?, randomskin = ? WHERE uuid = ?";
final PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, profile.getName() == null ? null : profile.getName());
statement.setString(2, profile.getSkin() == null ? null : profile.getSkin());
statement.setString(3, profile.getLocale().getCode());
- statement.setBoolean(4, profile.isBungeecordTransfer());
- statement.setBinaryStream(5, uuidToBin(uuid));
+ statement.setBoolean(4, profile.isRandomSkin());
+ statement.setString(5, uuid.toString());
return statement;
}
-
- private ByteArrayInputStream uuidToBin(UUID uuid) {
- byte[] bytes = new byte[16];
- ByteBuffer.wrap(bytes)
- .putLong(uuid.getMostSignificantBits())
- .putLong(uuid.getLeastSignificantBits());
- return new ByteArrayInputStream(bytes);
- }
}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorageProvider.java b/src/main/java/xyz/ineanto/nicko/storage/mariadb/MariaDBStorageProvider.java
similarity index 54%
rename from core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorageProvider.java
rename to src/main/java/xyz/ineanto/nicko/storage/mariadb/MariaDBStorageProvider.java
index 1a733e7..045e107 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/sql/SQLStorageProvider.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/mariadb/MariaDBStorageProvider.java
@@ -1,24 +1,24 @@
-package net.artelnatif.nicko.storage.sql;
+package xyz.ineanto.nicko.storage.mariadb;
-import net.artelnatif.nicko.config.Configuration;
-import net.artelnatif.nicko.config.DataSourceConfiguration;
-import net.artelnatif.nicko.storage.StorageProvider;
import org.mariadb.jdbc.MariaDbDataSource;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.config.DataSourceConfiguration;
+import xyz.ineanto.nicko.storage.StorageProvider;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Logger;
-public class SQLStorageProvider implements StorageProvider {
- private final Logger logger = Logger.getLogger("SQLStorageProvider");
+public class MariaDBStorageProvider implements StorageProvider {
+ private final Logger logger = Logger.getLogger("MariaDBStorageProvider");
private final Configuration configuration;
private Connection connection;
private final String schemaName = "nicko";
- public SQLStorageProvider(Configuration configuration) {
+ public MariaDBStorageProvider(Configuration configuration) {
this.configuration = configuration;
}
@@ -26,11 +26,12 @@ public class SQLStorageProvider implements StorageProvider {
public boolean init() {
try {
final MariaDbDataSource dataSource = new MariaDbDataSource();
- final DataSourceConfiguration dataSourceConfiguration = configuration.getSqlConfiguration();
- dataSource.setUrl("jdbc:mariadb://" + dataSourceConfiguration.getAddress() + ":" + dataSourceConfiguration.getPort());
- dataSource.setUser(dataSourceConfiguration.getUsername());
- dataSource.setPassword(dataSourceConfiguration.getPassword());
+ final DataSourceConfiguration sqlConfiguration = configuration.getSqlConfiguration();
+ dataSource.setUrl("jdbc:mariadb://" + sqlConfiguration.getAddress() + ":" + sqlConfiguration.getPort());
+ dataSource.setUser(sqlConfiguration.getUsername());
+ dataSource.setPassword(sqlConfiguration.getPassword());
connection = dataSource.getConnection();
+ connection.setAutoCommit(true);
final boolean initialized = connection != null && !connection.isClosed();
if (!initialized) return false;
@@ -39,7 +40,7 @@ public class SQLStorageProvider implements StorageProvider {
createTable();
return true;
} catch (SQLException e) {
- logger.severe("Couldn't establish a connection to the MySQL database: " + e.getMessage());
+ logger.severe("Couldn't establish a connection to the MariaDB database: " + e.getMessage());
return false;
}
}
@@ -57,30 +58,24 @@ public class SQLStorageProvider implements StorageProvider {
private void createTable() throws SQLException {
final Connection connection = getConnection();
-
- String query = "CREATE TABLE IF NOT EXISTS %s.DATA " +
- "(uuid binary(16) NOT NULL," +
- "name varchar(16)," +
- "skin varchar(16)," +
- "locale char(2) NOT NULL," +
- "bungeecord boolean NOT NULL," +
- "PRIMARY KEY (UUID))";
- query = query.replace("%s", schemaName);
+ final String query = "CREATE TABLE IF NOT EXISTS %s.DATA ".replace("%s", schemaName) +
+ "(uuid varchar(36) NOT NULL," +
+ "name varchar(16)," +
+ "skin varchar(16)," +
+ "locale char(2) NOT NULL," +
+ "bungeecord boolean NOT NULL," +
+ "PRIMARY KEY (uuid))";
final PreparedStatement statement = connection.prepareStatement(query);
statement.executeUpdate();
- statement.close();
}
private void createDatabase() throws SQLException {
final Connection connection = getConnection();
-
- String query = "CREATE DATABASE IF NOT EXISTS %s";
- query = query.replace("%s", schemaName);
+ final String query = "CREATE DATABASE IF NOT EXISTS %s".replace("%s", schemaName);
final PreparedStatement statement = connection.prepareStatement(query);
statement.executeUpdate();
- statement.close();
}
public Connection getConnection() {
diff --git a/src/main/java/xyz/ineanto/nicko/storage/mysql/MySQLStorage.java b/src/main/java/xyz/ineanto/nicko/storage/mysql/MySQLStorage.java
new file mode 100644
index 0000000..ae74d5f
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/mysql/MySQLStorage.java
@@ -0,0 +1,152 @@
+package xyz.ineanto.nicko.storage.mysql;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.appearance.Appearance;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.language.Language;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.Storage;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+public class MySQLStorage extends Storage {
+ private final Logger logger = Logger.getLogger("SQLStorage");
+ private final Configuration configuration;
+ private final Gson gson = new GsonBuilder().serializeNulls().create();
+
+ private MySQLStorageProvider provider;
+
+ public MySQLStorage(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public MySQLStorageProvider getProvider() {
+ if (provider == null) {
+ provider = new MySQLStorageProvider(configuration);
+ }
+ return provider;
+ }
+
+ @Override
+ public ActionResult store(UUID uuid, NickoProfile profile) {
+ final Connection connection = getProvider().getConnection();
+ if (connection == null) return ActionResult.error();
+
+ try {
+ final PreparedStatement statement = isStored(uuid) ?
+ getUpdateStatement(connection, uuid, profile) : getInsertStatement(connection, uuid, profile);
+ statement.executeUpdate();
+ return ActionResult.ok();
+ } catch (SQLException e) {
+ logger.warning("Couldn't send SQL Request: " + e.getMessage());
+ return ActionResult.error();
+ }
+ }
+
+ @Override
+ public boolean isStored(UUID uuid) {
+ final Connection connection = getProvider().getConnection();
+ if (connection == null) return false;
+
+ try {
+ final String sql = "SELECT uuid FROM nicko.DATA WHERE uuid = ?";
+
+ final PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setString(1, uuid.toString());
+
+ final ResultSet resultSet = statement.executeQuery();
+ return resultSet.next();
+ } catch (SQLException e) {
+ logger.warning("Couldn't check if data is present: " + e.getMessage());
+ return false;
+ }
+ }
+
+ @Override
+ public Optional retrieve(UUID uuid) {
+ final Connection connection = getProvider().getConnection();
+ if (connection == null) return Optional.empty();
+ if (!isStored(uuid)) return Optional.empty();
+
+ try {
+ final String sql = "SELECT * FROM nicko.DATA WHERE uuid = ?";
+
+ final PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setString(1, uuid.toString());
+
+ final ResultSet resultSet = statement.executeQuery();
+ String name = "";
+ String skin = "";
+ String locale = "";
+ boolean randomSkin = false;
+ List favorites = Collections.emptyList();
+ while (resultSet.next()) {
+ name = resultSet.getString("name");
+ skin = resultSet.getString("skin");
+ locale = resultSet.getString("locale");
+ randomSkin = resultSet.getBoolean("randomskin");
+ favorites = gson.fromJson(resultSet.getString("favorites"), new TypeToken>() { }.getType());
+ }
+
+ final NickoProfile profile = new NickoProfile(new Appearance(name, skin), Language.fromCode(locale), randomSkin, favorites);
+ return Optional.of(profile);
+ } catch (SQLException e) {
+ logger.warning("Couldn't fetch profile: " + e.getMessage());
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public ActionResult delete(UUID uuid) {
+ final Connection connection = getProvider().getConnection();
+ if (connection == null) return ActionResult.error();
+
+ try {
+ final String sql = "DELETE FROM nicko.DATA WHERE uuid = ?";
+ final PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setString(1, uuid.toString());
+ int rows = statement.executeUpdate();
+ return (rows == 1 ? ActionResult.ok() : ActionResult.error());
+ } catch (SQLException e) {
+ logger.warning("Couldn't delete profile: " + e.getMessage());
+ return ActionResult.error();
+ }
+ }
+
+ private PreparedStatement getInsertStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
+ final String sql = "INSERT IGNORE INTO nicko.DATA (`uuid`, `name`, `skin`, `locale`, `randomskin`, `favorites`) VALUES (?, ?, ?, ?, ?, ?)";
+ final PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setString(1, uuid.toString());
+ statement.setString(2, profile.getName() == null ? null : profile.getName());
+ statement.setString(3, profile.getSkin() == null ? null : profile.getSkin());
+ statement.setString(4, profile.getLocale().getCode());
+ statement.setBoolean(5, profile.isRandomSkin());
+
+ // Ineanto, 08/06/2025: this will never fucking work
+ statement.setString(6, gson.toJson(profile.getFavorites(), new TypeToken>() { }.getRawType()));
+ return statement;
+ }
+
+ private PreparedStatement getUpdateStatement(Connection connection, UUID uuid, NickoProfile profile) throws SQLException {
+ final String sql = "UPDATE nicko.DATA SET name = ?, skin = ?, locale = ?, randomskin = ? WHERE uuid = ?";
+ final PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setString(1, profile.getName() == null ? null : profile.getName());
+ statement.setString(2, profile.getSkin() == null ? null : profile.getSkin());
+ statement.setString(3, profile.getLocale().getCode());
+ statement.setBoolean(4, profile.isRandomSkin());
+ statement.setString(5, uuid.toString());
+ return statement;
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/storage/mysql/MySQLStorageProvider.java b/src/main/java/xyz/ineanto/nicko/storage/mysql/MySQLStorageProvider.java
new file mode 100644
index 0000000..41faea2
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/mysql/MySQLStorageProvider.java
@@ -0,0 +1,84 @@
+package xyz.ineanto.nicko.storage.mysql;
+
+import com.mysql.cj.jdbc.MysqlDataSource;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.config.DataSourceConfiguration;
+import xyz.ineanto.nicko.storage.StorageProvider;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+public class MySQLStorageProvider implements StorageProvider {
+ private final Logger logger = Logger.getLogger("MySQLStorageProvider");
+ private final Configuration configuration;
+
+ private Connection connection;
+
+ private final String schemaName = "nicko";
+
+ public MySQLStorageProvider(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public boolean init() {
+ try {
+ final MysqlDataSource dataSource = new MysqlDataSource();
+ final DataSourceConfiguration sqlConfiguration = configuration.getSqlConfiguration();
+ dataSource.setUrl("jdbc:mysql://" + sqlConfiguration.getAddress() + ":" + sqlConfiguration.getPort());
+ dataSource.setUser(sqlConfiguration.getUsername());
+ dataSource.setPassword(sqlConfiguration.getPassword());
+ connection = dataSource.getConnection();
+ connection.setAutoCommit(true);
+ final boolean initialized = connection != null && !connection.isClosed();
+
+ if (!initialized) return false;
+
+ createDatabase();
+ createTable();
+ return true;
+ } catch (SQLException e) {
+ logger.severe("Couldn't establish a connection to the MySQL database: " + e.getMessage());
+ return false;
+ }
+ }
+
+ @Override
+ public boolean close() {
+ if (connection == null) { return true; }
+ try {
+ connection.close();
+ return connection.isClosed();
+ } catch (SQLException e) {
+ return false;
+ }
+ }
+
+ private void createTable() throws SQLException {
+ final Connection connection = getConnection();
+ final String query = "CREATE TABLE IF NOT EXISTS %s.DATA ".replace("%s", schemaName) +
+ "(uuid varchar(36) NOT NULL," +
+ "name varchar(16)," +
+ "skin varchar(16)," +
+ "locale char(2) NOT NULL," +
+ "bungeecord boolean NOT NULL," +
+ "PRIMARY KEY (uuid))";
+
+ final PreparedStatement statement = connection.prepareStatement(query);
+ statement.executeUpdate();
+ }
+
+ private void createDatabase() throws SQLException {
+ final Connection connection = getConnection();
+ final String query = "CREATE DATABASE IF NOT EXISTS %s".replace("%s", schemaName);
+
+ final PreparedStatement statement = connection.prepareStatement(query);
+ statement.executeUpdate();
+ }
+
+ public Connection getConnection() {
+ return connection;
+ }
+}
diff --git a/core/src/main/java/net/artelnatif/nicko/storage/name/PlayerNameStore.java b/src/main/java/xyz/ineanto/nicko/storage/name/PlayerNameStore.java
similarity index 93%
rename from core/src/main/java/net/artelnatif/nicko/storage/name/PlayerNameStore.java
rename to src/main/java/xyz/ineanto/nicko/storage/name/PlayerNameStore.java
index c439d4e..1e90b11 100644
--- a/core/src/main/java/net/artelnatif/nicko/storage/name/PlayerNameStore.java
+++ b/src/main/java/xyz/ineanto/nicko/storage/name/PlayerNameStore.java
@@ -1,4 +1,4 @@
-package net.artelnatif.nicko.storage.name;
+package xyz.ineanto.nicko.storage.name;
import org.bukkit.entity.Player;
diff --git a/src/main/java/xyz/ineanto/nicko/storage/redis/RedisCache.java b/src/main/java/xyz/ineanto/nicko/storage/redis/RedisCache.java
new file mode 100644
index 0000000..b40367e
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/redis/RedisCache.java
@@ -0,0 +1,79 @@
+package xyz.ineanto.nicko.storage.redis;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.exceptions.JedisException;
+import xyz.ineanto.nicko.appearance.ActionResult;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.language.LanguageKey;
+import xyz.ineanto.nicko.profile.NickoProfile;
+import xyz.ineanto.nicko.storage.Cache;
+import xyz.ineanto.nicko.storage.CacheProvider;
+
+import java.util.Optional;
+import java.util.UUID;
+
+public class RedisCache extends Cache {
+ private final Gson gson = new GsonBuilder()
+ .serializeNulls()
+ .setPrettyPrinting()
+ .create();
+ private final Configuration configuration;
+ private RedisCacheProvider provider;
+
+ public RedisCache(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public CacheProvider getProvider() {
+ if (provider == null) {
+ provider = new RedisCacheProvider(configuration);
+ }
+ return provider;
+ }
+
+ @Override
+ public ActionResult cache(UUID uuid, NickoProfile profile) {
+ try (Jedis jedis = provider.getJedis()) {
+ jedis.set("nicko:" + uuid.toString(), gson.toJson(profile));
+ return ActionResult.ok();
+ } catch (JedisException exception) {
+ return ActionResult.error(LanguageKey.Error.CACHE);
+ }
+ }
+
+ @Override
+ public boolean isCached(UUID uuid) {
+ try (Jedis jedis = provider.getJedis()) {
+ return jedis.exists("nicko:" + uuid.toString());
+ } catch (JedisException exception) {
+ return false;
+ }
+ }
+
+ @Override
+ public Optional retrieve(UUID uuid) {
+ try (Jedis jedis = provider.getJedis()) {
+ // 06/07/25: like, for real. what the f is that comment about...?
+ // 08/29/23: what the fuck was I talking about?
+ // old_todo (Ineanto, 05/20/23): Check if cached before because Jedis returns a bulk reply so this is unsafe
+ final String data = jedis.get("nicko:" + uuid.toString());
+ final NickoProfile profile = gson.fromJson(data, NickoProfile.class);
+ return Optional.of(profile);
+ } catch (JedisException exception) {
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public ActionResult delete(UUID uuid) {
+ try (Jedis jedis = provider.getJedis()) {
+ jedis.del("nicko:" + uuid.toString());
+ return ActionResult.ok();
+ } catch (JedisException exception) {
+ return ActionResult.error(LanguageKey.Error.CACHE);
+ }
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/storage/redis/RedisCacheProvider.java b/src/main/java/xyz/ineanto/nicko/storage/redis/RedisCacheProvider.java
new file mode 100644
index 0000000..7408326
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/storage/redis/RedisCacheProvider.java
@@ -0,0 +1,38 @@
+package xyz.ineanto.nicko.storage.redis;
+
+import redis.clients.jedis.exceptions.JedisConnectionException;
+import xyz.ineanto.nicko.config.Configuration;
+import xyz.ineanto.nicko.config.DataSourceConfiguration;
+import xyz.ineanto.nicko.storage.CacheProvider;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+
+public class RedisCacheProvider implements CacheProvider {
+ private final Configuration configuration;
+ private JedisPool pool;
+
+ public RedisCacheProvider(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ public boolean init() {
+ final DataSourceConfiguration redisConfiguration = configuration.getRedisConfiguration();
+ pool = new JedisPool(redisConfiguration.getAddress(), redisConfiguration.getPort());
+ try {
+ return !pool.isClosed() && pool.getResource() != null;
+ } catch (JedisConnectionException exception) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean close() {
+ pool.close();
+ return pool.isClosed();
+ }
+
+ public Jedis getJedis() {
+ return pool.getResource();
+ }
+}
diff --git a/src/main/java/xyz/ineanto/nicko/version/Version.java b/src/main/java/xyz/ineanto/nicko/version/Version.java
new file mode 100644
index 0000000..5b95ac0
--- /dev/null
+++ b/src/main/java/xyz/ineanto/nicko/version/Version.java
@@ -0,0 +1,33 @@
+package xyz.ineanto.nicko.version;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Comparator;
+
+public record Version(int major, int minor, int patch) implements Comparable {
+ @Override
+ public int compareTo(@NotNull Version otherVersion) {
+ final Comparator comparator = Comparator
+ .comparingInt(Version::major)
+ .thenComparingInt(Version::minor)
+ .thenComparingInt(Version::patch);
+ return comparator.compare(this, otherVersion);
+ }
+
+ @Override
+ public @NotNull String toString() {
+ return major + "." + minor + "." + patch;
+ }
+
+ public static Version fromString(String versionString) {
+ if (versionString == null || versionString.isEmpty()) { return new Version(0, 0, 0); }
+ final String[] split = versionString.split("\\.");
+ try {
+ return new Version(Integer.parseInt(split[0]),
+ Integer.parseInt(split[1]),
+ Integer.parseInt(split[2]));
+ } catch (NumberFormatException exception) {
+ return new Version(0, 0, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/resources/config.yml b/src/main/resources/config.yml
similarity index 62%
rename from core/src/main/resources/config.yml
rename to src/main/resources/config.yml
index 22f718a..0ed717d 100644
--- a/core/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -1,16 +1,23 @@
-# Nicko ${project.version} - Config:
+# Nicko ${version} - Config:
-###########
-# STORAGE #
-###########
+# Specifies the configuration version, don't change.
+version: "1.2.0"
-# Indicates wherever the data will be stored
-# locally through a .json file or a (My)SQL database.
+# Nicko will copy the English locale as "lang.yml"
+# and will use the translations in that file when "Server Custom"
+# is selected as the player's locale.
# Accepted values: false (Disabled), true (Enabled)
-local: true
+customLocale: false
-# This configuration section manages SQL.
sql:
+ # Indicates wherever the data will be stored locally
+ # inside a .json file or in an SQL database.
+ # Accepted values: false (Disabled), true (Enabled)
+ enabled: false
+ # Toggles between the MariaDB and MySQL drivers.
+ # If you use the MySQL database engine, switch this to off.
+ # Accepted values: false (Disabled), true (Enabled)
+ mariadb: true
# SQL database's address
# Accepted values: valid IP address (e.g. localhost, 127.0.0.1)
address: "localhost"
@@ -24,15 +31,13 @@ sql:
# Accepted values: any string
password: "password"
-# This configuration section manages Redis (BungeeCord support).
-# It is used to transfer data between multiple servers.
redis:
# Indicates wherever the data will be stored through
# Redis to transfer whenever a player switches server.
# Accepted values: false (Disabled), true (Enabled)
enabled: false
# Redis server's address
- # Accepted values: valid IP address (e.g. localhost, 127.0.0.1)
+ # Accepted values: valid IP address (e.g.: localhost, 127.0.0.1)
address: "localhost"
# Redis server's port
# Accepted values: valid integer (e.g. 3306, 25565)
@@ -42,18 +47,4 @@ redis:
username: "username"
# Redis server's password
# Accepted values: any string
- password: "password"
-
-###########
-# DISPLAY #
-###########
-
-# Nicko's messages prefix.
-# Accepted values: any string
-prefix: "§6Nicko §8§l| §r"
-
-# Nicko will copy the English locale as "lang.yml"
-# and will use the translations in that file when "Server Custom"
-# is selected as the player's locale.
-# Accepted values: false (Disabled), true (Enabled)
-customLocale: false
\ No newline at end of file
+ password: "password"
\ No newline at end of file
diff --git a/src/main/resources/en.yml b/src/main/resources/en.yml
new file mode 100644
index 0000000..afa9439
--- /dev/null
+++ b/src/main/resources/en.yml
@@ -0,0 +1,175 @@
+# Nicko ${version} - Language File:
+
+# Specifies the configuration version, don't change.
+version: "1.4.0"
+
+prefix: "NICKO"
+whoosh: "WHOOSH!"
+oops: "OOPS!"
+
+error:
+ permission: "You're missing the permission to do that."
+ invalid_username: "This is an invalid Minecraft username."
+ mojang: "Something went wrong while fetching data from Mojang."
+ cache: "Unable to get data from the cache."
+
+event:
+ settings:
+ error: "Wasn''t able to update your settings! ({0})"
+ appearance:
+ set:
+ error: "Wasn''t able to apply your disguise! ({0})"
+ ok: "You''re now disguised."
+ chat_prompt_name: "Please enter your new name in chat (type \"EXIT\" to cancel)."
+ chat_prompt_skin: "Please enter your new skin in chat (type \"EXIT\" to cancel)."
+ restore:
+ error: "Wasn''t able to apply the previous disguise! ({0})"
+ ok: "Previous disguise restored."
+ remove:
+ error: "Wasn''t able to remove your disguise!."
+ missing: "You''re not currently disguised."
+ ok: "Undisguised successfully."
+ admin:
+ cache:
+ invalidate_cache: "Cache purged."
+ invalidate_entry: "{0} was purged."
+ check:
+ remove_skin: "Skin removed from player."
+
+gui:
+ title:
+ home: "Nicko"
+ settings: "Settings"
+ admin: "Administration"
+ check: "Player Management"
+ confirm: "Are you sure?"
+ cache: "Cache Management"
+ invalidate_skin: "Purge cache..."
+ favorites: "Favorites"
+
+ exit:
+ name: "Exit"
+ go_back:
+ name: "Back"
+ unavailable:
+ name: "Unavailable"
+ lore:
+ - "This button is disabled."
+ error:
+ name: "Error!"
+ lore:
+ - "The item failed to load, but it might still work."
+ loading:
+ name: "Loading..."
+ choice:
+ confirm:
+ name: "Confirm"
+ choose:
+ name: "Choose an option..."
+ cancel:
+ name: "Cancel"
+ scroll_up:
+ name: "Scroll up"
+ lore:
+ - "(You can't scroll any higher.)"
+ scroll_down:
+ name: "Scroll down"
+ lore:
+ - "(You can't scroll any further down.)"
+ new_skin:
+ name: "New skin..."
+ new_name:
+ name: "New name..."
+ home:
+ admin:
+ name: "Administration panel"
+ lore:
+ - "Configure and manage Nicko."
+ settings:
+ name: "Settings"
+ lore:
+ - "Fine tune your experience with Nicko."
+ change_name:
+ name: "Change your nickname"
+ change_skin:
+ name: "Change your skin"
+ change_both:
+ name: "Change both"
+ random_skin:
+ name: "I feel lucky!"
+ reset:
+ name: "Reset appearance"
+ lore:
+ - "Completely remove your disguise."
+ favorites:
+ name: "Favorites"
+ lore:
+ - "List all your favorites appearances."
+ admin:
+ manage_cache:
+ name: "Manage the skin cache..."
+ lore:
+ - "View and manage the skin cache."
+ manage_player:
+ name: "Inspect a player..."
+ lore:
+ - "See players' disguise information."
+ check:
+ name: "{0}"
+ lore:
+ - "Nicked: {1}"
+ - "Name: {2}"
+ - "Skin: {3}"
+ - " "
+ - "Click to remove skin!"
+ cache:
+ statistics:
+ name: "Statistics"
+ lore:
+ - "Request count: {0}"
+ - "Number of skin cached: {1}"
+ - "Cache is cleared every 24 hours."
+ invalidate_cache:
+ name: "Invalidate cache"
+ lore:
+ - "NOT RECOMMENDED"
+ - "Invalidate the entirety of the skin cache."
+ - "This doesn't reset player's disguises."
+ invalidate_skin:
+ name: "Invalidate a skin..."
+ lore:
+ - "Select a specific skin to invalidate."
+ - "Useful if a skin has been recently updated."
+ entry:
+ name: "{0}"
+ lore:
+ - "Click to invalidate..."
+ settings:
+ toggleable_button:
+ lore:
+ - "{0} Disabled"
+ - "{1} Enabled"
+ cycling_choices:
+ lore:
+ - "Cycle through the values"
+ - "by left or right clicking."
+ language:
+ name: "Language"
+ random_skin:
+ name: "Random skin on login"
+ favorites:
+ add:
+ name: "Add a favorite"
+ lore:
+ - "Add a new favorite appearance to the list."
+ - "Hold SHIFT to add your current disguise!"
+ remove:
+ name: "Toggle deletion mode"
+ lore:
+ - "Clicking on any disguise as this mode is"
+ - "active will remove it from your favorites."
+ entry:
+ name: "Favorite"
+ lore:
+ - "Name: {0}"
+ - "Skin: {1}"
\ No newline at end of file
diff --git a/src/main/resources/fr.yml b/src/main/resources/fr.yml
new file mode 100644
index 0000000..109a887
--- /dev/null
+++ b/src/main/resources/fr.yml
@@ -0,0 +1,177 @@
+# Nicko ${version} - Fichier de langue:
+
+# Précise la version de la configuration, ne pas changer.
+version: "1.4.0"
+
+prefix: "NICKO"
+whoosh: "WHOOSH!"
+oops: "OOPS!"
+
+error:
+ permission: "Vous n'avez pas la permission de faire cela."
+ invalid_username: "Nom d'utilisateur Minecraft invalide."
+ mojang: "Une erreur est surevenue en récupérant les information depuis Mojang."
+ cache: "Impossible de récupérer les données depuis le cache."
+
+event:
+ settings:
+ error: "Impossible de mettre à jour vos paramètres ! ({0})"
+ appearance:
+ set:
+ error: "Impossible d''appliquer votre déguisement ! ({0})"
+ ok: "Déguisement appliqué avec succès."
+ chat_prompt_name: "Veuillez entrer votre nouveau pseudo (saisissez \"EXIT\" pour arrêter)."
+ chat_prompt_skin: "Veuillez entrer votre nouveau skin (saisissez \"EXIT\" pour arrêter)."
+ restore:
+ error: "Impossible d''appliquer le précédent déguisement ! ({0})"
+ ok: "Votre précédent déguisement a été appliqué."
+ remove:
+ error: "Impossible de retirer votre déguisement."
+ missing: "Vous n''avez pas de déguisement."
+ ok: "Déguisement retiré."
+ admin:
+ cache:
+ invalidate_cache: "Cache complet invalidé."
+ invalidate_entry: "{0} a été invalidé."
+ check:
+ remove_skin: "Déguisement retiré au joueur."
+
+gui:
+ title:
+ home: "Nicko"
+ settings: "Paramètres"
+ admin: "Administration"
+ check: "Gestion des Joueurs"
+ confirm: "Êtes-vous sûr ?"
+ cache: "Gestion du Cache"
+ invalidate_skin: "Purge du cache..."
+ favorites: "Favoris"
+
+ exit:
+ name: "Quitter"
+ go_back:
+ name: "Retour"
+ unavailable:
+ name: "Indisponible"
+ lore:
+ - "Ce boutton est désactivé."
+ error:
+ name: "Erreur !"
+ lore:
+ - "La texture de l'objet n'a pas chargé"
+ - "correctement mais il fonctionne encore."
+ loading:
+ name: "Chargement..."
+ choice:
+ confirm:
+ name: "Confirmer"
+ choose:
+ name: "Choisissez une option..."
+ cancel:
+ name: "Annuler"
+ scroll_up:
+ name: "Défiler vers le haut"
+ lore:
+ - "(Impossible de défiler plus haut.)"
+ scroll_down:
+ name: "Défiler vers le bas"
+ lore:
+ - "(Impossible de défiler plus bas.)"
+ new_skin:
+ name: "Nouveau skin..."
+ new_name:
+ name: "Nouveau nom..."
+ home:
+ admin:
+ name: "Panel d'administration"
+ lore:
+ - "Configurez et gérez Nicko."
+ settings:
+ name: "Paramètres"
+ lore:
+ - "Gérez votre expérience avec Nicko."
+ change_name:
+ name: "Changer le pseudo"
+ change_skin:
+ name: "Changer le skin"
+ change_both:
+ name: "Changer les deux"
+ random_skin:
+ name: "Je me sens chanceux !"
+ reset:
+ name: "Réinitialiser l'apparence"
+ lore:
+ - "Supprime complètement votre déguisement."
+ favorites:
+ name: "Favoris"
+ lore:
+ - "Listez toutes vos apparences favorites."
+ admin:
+ manage_cache:
+ name: "Gérer le cache de skin..."
+ lore:
+ - "Consultez et gérez le cache de skin."
+ manage_player:
+ name: "Vérifier un joueur..."
+ lore:
+ - "Vérifiez les informations de déguisement d'un joueur."
+ check:
+ name: "{0}"
+ lore:
+ - "Déguisé: {1}"
+ - "Nom: {2}"
+ - "Skin: {3}"
+ - " "
+ - "Cliquez pour retirer le skin !"
+ cache:
+ statistics:
+ name: "Statistiques"
+ lore:
+ - "Nombre de requêtes: {0}"
+ - "Nb. de skin dans le cache: {1}"
+ - "Le cache est vidé toutes les 24 heures."
+ invalidate_cache:
+ name: "Purger le cache"
+ lore:
+ - "DÉCONSEILLÉ"
+ - "Purge l'entièreté du cache des skin."
+ - "Ne retire pas les déguisements des joueurs."
+ invalidate_skin:
+ name: "Invalider un skin..."
+ lore:
+ - "Sélectionnez une apparence spécifique à"
+ - "invalider. Utile dans le cas où un skin"
+ - "a récemment été mis à jour."
+ entry:
+ name: "{0}"
+ lore:
+ - "Cliquez pour invalider..."
+ settings:
+ toggleable_button:
+ lore:
+ - "{0} Désactivé"
+ - "{1} Activé"
+ cycling_choices:
+ lore:
+ - "Parcourez les valeurs"
+ - "avec un clique gauche/droit."
+ language:
+ name: "Langage"
+ random_skin:
+ name: "Apparence aléatoire à la connexion"
+ favorites:
+ add:
+ name: "Ajouter un favori"
+ lore:
+ - "Ajoute une nouvelle apparence favorite."
+ - "Maintenez SHIFT pour ajouter votre apparence actuelle !"
+ remove:
+ name: "Activer la suppression"
+ lore:
+ - "Cliquer sur un déguisement lorsque le mode est"
+ - "actif le supprimera de vos favoris."
+ entry:
+ name: "Favori"
+ lore:
+ - "Nom: {0}"
+ - "Skin: {1}"
\ No newline at end of file
diff --git a/src/main/resources/names.txt b/src/main/resources/names.txt
new file mode 100644
index 0000000..0d54e92
--- /dev/null
+++ b/src/main/resources/names.txt
@@ -0,0 +1,490 @@
+w4nderlost
+TooParanoids
+Der_OG_31er
+9xxDaRkShAdOwxx9
+giiiaan_
+Jqstinnn
+Tillysboy92
+AlwaysCello
+SyndrexG0D
+Peypeycake
+ThePerjurer
+Tioe
+Elternbaum
+BarkersRover_16
+pebsso
+cyrus6950
+Bigest_guy
+RV0REU
+R379
+Shetell
+_HEAPASS_
+Iamaloner21
+TheFardoxGamerHD
+Flyboi43
+Cha0smusik
+kat00
+Infreat
+Crummymoofin
+MijnVriend
+momsrightkidney
+dmacrado
+Elephantman321
+ii_hamoudi_YT
+FaurePavane
+ambiezzz
+XD_Bandit695_XD
+Nabingo
+Cyl0re
+ku5
+SrAragon
+StarlightDream9
+CJ5370
+rainbees
+KeroTheWolf
+Andrews9722
+cursed_Assyrian
+yamateni
+ProgramEXE
+exprso
+harrypanda
+LookerMD
+migykins
+Wintrous
+ZzGaBi
+Flayber
+Grenixal
+maeve_wells
+Creeper10fr
+10Chairs
+2525lock
+Shqipe
+XenitsuZen
+Berno17_
+wolle1313
+HalfDogHalfCat1
+NachoGarcia
+popsicoal
+NemesiSevil2006
+AnywayOj
+Tanko12345
+Samdweck
+LYRECODE123
+Resulten
+SirBastii
+Maku056
+ItzArnizzz
+Brsh3620
+Masonita
+kapplanium
+shoezo
+Mansur203
+Waterboy15217
+redragonne
+ghko325
+HopePVP_tw7
+xtka
+NimwenxZ
+Hiro0408
+PanderaWz
+Shesu
+_Aniste_NY_
+Besceste
+3ee3
+ArcticGalaxy123
+snooze_mingo
+LizzyLomnh
+FaZeChulupa
+LineZeeK
+liabilaty
+BlackSheep1610
+Simif69
+Aficionado
+riekin
+XLuggas
+MathExams
+6fq
+Marveel
+lolme51
+TaioSayUwU
+Fonklift
+blvw
+Po1204
+Pierre_Rabbit
+mifimasters
+MrRidge1
+arnqen
+Nick_cage102
+Geo_9918
+SSShudder
+Nicolas_Mom
+WolfMatrix101
+frictionless_
+Gughik
+gold_dragon_4
+nealxero
+ClonedPickle
+SourWatermelonxX
+devilunion
+Daryifuny
+joaomarcos11
+Dekeef
+PadfootTheDog
+DarkScopez80
+flowers220
+Gaiiya
+The_Yeet_
+juuuuwu
+MrMafioz
+Surpasses
+TypicalOwen
+0lober
+Zerfixy
+Sunny3803b
+neostanley
+Creeper_Kart
+minestin
+Goldenfredster
+Vju
+MrArchI_YT
+Casper1709
+Backiii_
+DrCreate
+Nova_Lux1
+Jayvin_Blanco
+ShadowMan1770
+0KOPO40K
+Silk_Altermann69
+Alu____
+Honey_MilkExe112
+T0XEI
+CB_13
+Paragorn
+HaGiang
+Shivendra8i
+Mayflower47
+Not_Someguy
+raxx111bg
+IceyGlaceon
+grasseffect
+PoopTNTpvp
+codecyber
+Shrumpkin13
+Shqdown
+Cmartin82
+KTCXD_5p0tty
+rockesalt
+goldjeong
+TheRealAKD
+NamiSwaaan
+yaaratol
+Dikiy_Flexer
+PoLecker24
+_SakuraTree
+PikkOgP0rno
+HawksFang
+BlueWinterWolf
+hskmerk
+gurmaw
+Lunggor
+clashfield
+Zelaste
+ACommonMouse
+TJ_Mystery
+Dizzy3312
+Raindropsss
+minecraftxiaoju
+sachilovebbh
+Celina_LaZyCxt
+firered6
+55000000
+Illunarnati
+Jedidiah2003
+setomz1
+basically_e
+TommyGreif02
+Bongrip42069
+Coco_Keopi
+Lt_Colt
+Kuurotta
+GqmeKnight
+WinCo_Foods
+FKDLZ
+IanPumpkin
+tastywtf
+natedawg0
+ZQLFenyx
+GamerMaster110
+papajobi9
+Yucaroon
+Xion_69
+AirJaw
+funfun321234
+khalleesii
+Pozisch
+thorso15
+kyumisoup
+Leonqrd
+BmwDreamer
+TehRos
+pitplayer69
+_ve0
+Miss_Yuka
+I_am_a_Bucket
+nicolas_bean
+xHorizonGC
+RTX3060_
+Borec188
+c8to
+megan3groCENG
+ventriloquize
+galczin
+Scorch3dEarth3d
+nightstarLP
+VittyGam3r
+GLaDOS__
+hydrelo
+JustACarter
+MikeDropperPlay
+NorthernWest
+_Skelesam_
+ZX_Style
+Tamas_Boi
+taylub
+VyacheslavO_O
+trippyaubs
+udtpic
+Lunarglow
+Stoolman
+legendary_meow
+Loganii
+CaptainStain56
+FoofieGeto
+Judgeavapl
+OneBigDigger
+Sorem13
+Raisonneur
+IlkoalI
+Naxa
+craigbabyonebay
+NicholasG04
+UtopianCrisi
+CalamarPasGenti
+ryluh_
+Aceslimz
+Howardygh99927
+brandon257
+MarcoswildHD
+x_XSkylerX_x
+Bronco09
+That_Kookie_
+Danigtz
+Ricky_lol
+999keyt
+Thilow15
+Difesito
+ostehovl
+isacano_12
+big_esra
+secretbaguette
+MrCommunism
+Jekube
+GrandeMaster
+DrGrip
+TheArnek
+JacsMars
+Lliam14
+MrGameandWatch84
+Rinzap
+XrazzeD
+ukknown
+ZohanPrent
+Naspo
+Rajem
+VepiGHG
+matoureal
+BrianChen87
+Jrocky
+stivo999
+Des_cole
+ReqGames
+Kingja1912
+issssyy
+Apache424
+Nick_Zockt_
+Mr_Haider_10
+ValentineBun
+fedorPro228
+xTilz
+blockbuster02k
+4ck
+FrostedTree
+VegasTortoise
+ZBellaV12121
+paypales
+qDread
+itsRiven
+i8oreo
+_kimcream_
+Phisuss
+Oscargray
+Elsiff
+callofdutydog00
+BruhTheMoment
+Pazmaa
+MythicalOak
+komuchi33
+awf4
+Jacobsaurus21
+itsjohannaa
+Jello12
+Adrien183
+jajazzywazzy
+Jorjie22
+SuperBrawlr5788
+KaraageV
+_Hanime_tv
+Padilhao
+Tikkas
+ordinaryducky
+Mothytix95
+renopotouwu
+1000voices
+niclas05
+Felipstein
+DoutorBauer
+FireballPlaysMC
+vapelordsheep
+Aboain
+ImGrexy
+Aivokolo
+SuperAmazing101
+va75a77a
+_DawYans_
+AceT1223
+Livvyboo7
+Saaaaaaaaaaaaans
+okaychill
+AwesomeBro1122
+absolutesnek
+jogie5000
+curtainSenpai
+gabbyisaloser
+gamergurl6969
+ZeusDk
+FranaRibas
+Discoboss
+SYZ_1
+Nakoe
+FIU_Captive
+xSiFan_
+ilyDeathxz
+da_fipsi
+Lochy
+The_Lavie37
+Tonion
+vnvrchy
+xX0meg4Xx
+haohxtheone
+VtTronic
+xDaniGum
+tikkelill
+DatYoshi
+eyehamstewpit
+nicholas460_
+Memsly445
+nugunugu
+AndreSlayz
+jashik1
+Qweenoftheocean
+Coltable
+treblaclef
+Kisaxx
+69Dxddy69
+RaulCuh
+3Wheat
+_OscarTheGrouch
+oIsqk
+Blockbusterweng
+AntoineDegauss
+ValeIsTheBest
+SwaggyCrabby
+DieOfSanity
+SirenMC
+Jade_Jewel
+Tropic44
+666splendor
+TallnessTallness
+breadgang9827
+Muffin_Worlds
+DedicatedVeggie
+Gonzalox_7
+datrandomasian
+Chasemon01
+Nyavix
+Lonely_Summers
+_RoveN
+ok_kyro
+LN_hunter
+saharsabz
+Roselilianna
+Gadx
+xtytan
+RoRo_levosgien88
+Bowsesqe_21
+Bennett528
+TheShipSailsWest
+KaiserGaming
+Layna_Shinozaki
+OP_greatly
+D3rpTaco
+Loufink
+Jorlmungus
+Snichol1801
+Ludixeo
+Imoeto
+MarshallNebunu
+crazycrystals
+Parapatus
+HahaDani
+MrQuaring
+DonTurnt
+SailorRoberts101
+FluffieBear
+TripleThick
+KingSparta
+MummysHome
+Cooga3
+Technosista
+Youmerstudios
+SkyyRaine
+criss102
+mrfailt
+CraftingBasic
+qnxkdifh
+Igorex2k20
+LaLisette
+ReBoredGamer
+warlordwest
+ExoTemporal
+KingLonmc
+666Horus
+IslandCity2
+TheBigSavage1
+Trishke2003
+skyrowin
+Krissy3D
+AntonWTobias
+SaddyWasTaken
+Ahoy_Peko_Hao_Yo
+T4nTr1Ss
+aleciolike
+ninja_shenley
+Lordmord1337
+eatmypoopfather
+Ktanner
+The42OWeedGOD
+CooperBee
+_MikuMiku_
+althume
+Tr3bba93
\ No newline at end of file
diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml
new file mode 100644
index 0000000..f515c80
--- /dev/null
+++ b/src/main/resources/paper-plugin.yml
@@ -0,0 +1,24 @@
+name: Nicko
+main: xyz.ineanto.nicko.Nicko
+loader: xyz.ineanto.nicko.loader.NickoPluginLoader
+version: ${version}
+author: Ineanto
+description: "The feature packed, next generation disguise plugin for Minecraft."
+api-version: "1.21"
+softdepend: [ PlaceholderAPI ]
+depend:
+ - ProtocolLib
+
+dependencies:
+ server:
+ ProtocolLib:
+ load: BEFORE
+ join-classpath: true
+
+permissions:
+ nicko.*:
+ default: op
+ children:
+ - nicko.use
+ nicko.use:
+ default: false
\ No newline at end of file
diff --git a/v1_13_R1/pom.xml b/v1_13_R1/pom.xml
deleted file mode 100644
index 6aa987b..0000000
--- a/v1_13_R1/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_13_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.13-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_13_R1/src/main/java/net/artelnatif/nicko/impl/v1_13_R1.java b/v1_13_R1/src/main/java/net/artelnatif/nicko/impl/v1_13_R1.java
deleted file mode 100644
index 013ddd4..0000000
--- a/v1_13_R1/src/main/java/net/artelnatif/nicko/impl/v1_13_R1.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_13_R1.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_13_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_13_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final WorldServer worldServer = entityPlayer.getWorldServer();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(worldServer.dimension,
- worldServer.getDifficulty(),
- worldServer.worldData.getType(),
- entityPlayer.playerInteractManager.getGameMode());
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_13_R1.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_13_R2/pom.xml b/v1_13_R2/pom.xml
deleted file mode 100644
index 1e1606a..0000000
--- a/v1_13_R2/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_13_R2
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.13.2-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_13_R2/src/main/java/net/artelnatif/nicko/impl/v1_13_R2.java b/v1_13_R2/src/main/java/net/artelnatif/nicko/impl/v1_13_R2.java
deleted file mode 100644
index ada42dc..0000000
--- a/v1_13_R2/src/main/java/net/artelnatif/nicko/impl/v1_13_R2.java
+++ /dev/null
@@ -1,128 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_13_R2.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_13_R2 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final WorldServer worldServer = entityPlayer.getWorldServer();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(worldServer.dimension,
- worldServer.getDifficulty(),
- worldServer.S(),
- entityPlayer.playerInteractManager.getGameMode());
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_13_R2.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_14_R1/pom.xml b/v1_14_R1/pom.xml
deleted file mode 100644
index f69fa93..0000000
--- a/v1_14_R1/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_14_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.14.4-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_14_R1/src/main/java/net/artelnatif/nicko/impl/v1_14_R1.java b/v1_14_R1/src/main/java/net/artelnatif/nicko/impl/v1_14_R1.java
deleted file mode 100644
index 8cb1887..0000000
--- a/v1_14_R1/src/main/java/net/artelnatif/nicko/impl/v1_14_R1.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_14_R1.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_14_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.getWorldServer().getWorldProvider().getDimensionManager(),
- entityPlayer.getWorld().P(),
- entityPlayer.playerInteractManager.getGameMode());
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_14_R1.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_15_R1/pom.xml b/v1_15_R1/pom.xml
deleted file mode 100644
index 783358e..0000000
--- a/v1_15_R1/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_15_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.15.2-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_15_R1/src/main/java/net/artelnatif/nicko/impl/v1_15_R1.java b/v1_15_R1/src/main/java/net/artelnatif/nicko/impl/v1_15_R1.java
deleted file mode 100644
index 1bffee0..0000000
--- a/v1_15_R1/src/main/java/net/artelnatif/nicko/impl/v1_15_R1.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_15_R1.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_15_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final CraftWorld world = entityPlayer.getWorld().getWorld();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.getWorldServer().getWorldProvider().getDimensionManager(),
- world.getSeed(),
- entityPlayer.getWorld().P(),
- entityPlayer.playerInteractManager.getGameMode());
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_16_R1/pom.xml b/v1_16_R1/pom.xml
deleted file mode 100644
index 032d146..0000000
--- a/v1_16_R1/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_16_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.16.1-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_16_R1/src/main/java/net/artelnatif/nicko/impl/v1_16_R1.java b/v1_16_R1/src/main/java/net/artelnatif/nicko/impl/v1_16_R1.java
deleted file mode 100644
index c7939c1..0000000
--- a/v1_16_R1/src/main/java/net/artelnatif/nicko/impl/v1_16_R1.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_16_R1.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_16_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_16_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_16_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.getWorld().getDimensionKey();
- final CraftWorld world = entityPlayer.getWorld().getWorld();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.getWorld().getTypeKey(),
- levelResourceKey, world.getSeed(),
- entityPlayer.playerInteractManager.c(), entityPlayer.playerInteractManager.getGameMode(),
- false,
- false,
- false);
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_16_R1.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_16_R2/pom.xml b/v1_16_R2/pom.xml
deleted file mode 100644
index 658413d..0000000
--- a/v1_16_R2/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_16_R2
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.16.3-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_16_R2/src/main/java/net/artelnatif/nicko/impl/v1_16_R2.java b/v1_16_R2/src/main/java/net/artelnatif/nicko/impl/v1_16_R2.java
deleted file mode 100644
index 244970a..0000000
--- a/v1_16_R2/src/main/java/net/artelnatif/nicko/impl/v1_16_R2.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_16_R2.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_16_R2.CraftWorld;
-import org.bukkit.craftbukkit.v1_16_R2.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_16_R2 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.getWorld().getDimensionKey();
- final CraftWorld world = entityPlayer.getWorld().getWorld();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.getWorld().getDimensionManager(),
- levelResourceKey, world.getSeed(),
- entityPlayer.playerInteractManager.c(), entityPlayer.playerInteractManager.getGameMode(),
- false,
- false,
- false);
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_16_R2.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_16_R3/pom.xml b/v1_16_R3/pom.xml
deleted file mode 100644
index 055dbe2..0000000
--- a/v1_16_R3/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_16_R3
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.16.5-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_16_R3/src/main/java/net/artelnatif/nicko/impl/v1_16_R3.java b/v1_16_R3/src/main/java/net/artelnatif/nicko/impl/v1_16_R3.java
deleted file mode 100644
index b0744ea..0000000
--- a/v1_16_R3/src/main/java/net/artelnatif/nicko/impl/v1_16_R3.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.google.common.collect.Lists;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.server.v1_16_R3.*;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
-import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-
-public class v1_16_R3 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.getWorld().getDimensionKey();
- final CraftWorld world = entityPlayer.getWorld().getWorld();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.getWorld().getDimensionManager(),
- levelResourceKey, world.getSeed(),
- entityPlayer.playerInteractManager.c(), entityPlayer.playerInteractManager.getGameMode(),
- false,
- false,
- false);
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.playerConnection.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.playerConnection.sendPacket(destroy);
- onlineEntityPlayer.playerConnection.sendPacket(spawn);
- }
- onlineEntityPlayer.playerConnection.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
- final IChatBaseComponent name = new ChatComponentText(profileName);
-
- // ok so what the actual fuck
- // the PlayerDataInfo inner class is NOT static
- // thus the compiler can't access it when compiling??????
- // i swear this is so dumb that I have to resort to doing this
- final Object infoData = yes(
- add,
- gameProfile,
- entityPlayer.ping,
- EnumGamemode.getById(player.getGameMode().ordinal()),
- name
- );
- spoofPlayerInfoPacket(add, Lists.newArrayList(infoData));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.playerConnection.sendPacket(remove);
- onlineEntityPlayer.playerConnection.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-
- public Object yes(PacketPlayOutPlayerInfo packet, GameProfile gameProfile, int ping, EnumGamemode gamemode, IChatBaseComponent name) {
- try {
- final Class> clazz = Class.forName("net.minecraft.server.v1_16_R3.PacketPlayOutPlayerInfo$PlayerInfoData");
- final Constructor> infoConstructor = clazz.getDeclaredConstructor(
- PacketPlayOutPlayerInfo.class,
- GameProfile.class,
- int.class,
- EnumGamemode.class,
- IChatBaseComponent.class
- );
- return infoConstructor.newInstance(packet, gameProfile, ping, gamemode, name);
- } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException | InstantiationException |
- IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to instantiate PlayerInfoData, that's bad! (" + e.getMessage() + ")");
- return null;
- }
- }
-}
diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml
deleted file mode 100644
index 7ca2642..0000000
--- a/v1_17_R1/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- nicko-parent
- net.artelnatif
- 1.0-SNAPSHOT
-
- 4.0.0
-
- v1_17_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.17.1-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_17_R1/src/main/java/net/artelnatif/nicko/impl/v1_17_R1.java b/v1_17_R1/src/main/java/net/artelnatif/nicko/impl/v1_17_R1.java
deleted file mode 100644
index 24cd2a0..0000000
--- a/v1_17_R1/src/main/java/net/artelnatif/nicko/impl/v1_17_R1.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.network.chat.IChatBaseComponent;
-import net.minecraft.network.protocol.game.*;
-import net.minecraft.network.syncher.DataWatcher;
-import net.minecraft.network.syncher.DataWatcherObject;
-import net.minecraft.network.syncher.DataWatcherRegistry;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.server.level.EntityPlayer;
-import net.minecraft.world.level.EnumGamemode;
-import net.minecraft.world.level.World;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-public class v1_17_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.getWorld().getDimensionKey();
- final CraftWorld world = entityPlayer.getWorld().getWorld();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.getWorld().getDimensionManager(),
- levelResourceKey, world.getSeed(),
- entityPlayer.c.getGamemode(), entityPlayer.d.c(),
- false,
- false,
- false);
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.b.sendPacket(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.getDataWatcher();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.set(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.b.sendPacket(destroy);
- onlineEntityPlayer.b.sendPacket(spawn);
- }
- onlineEntityPlayer.b.sendPacket(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.e, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a);
-
- add.b().clear();
- add.b().add(new PacketPlayOutPlayerInfo.PlayerInfoData(gameProfile,
- player.getPing(),
- EnumGamemode.getById(player.getGameMode().ordinal()), IChatBaseComponent.a(profileName)));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.b.sendPacket(remove);
- onlineEntityPlayer.b.sendPacket(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-}
diff --git a/v1_18_R1/pom.xml b/v1_18_R1/pom.xml
deleted file mode 100644
index d842952..0000000
--- a/v1_18_R1/pom.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 4.0.0
-
-
- net.artelnatif
- nicko-parent
- 1.0-SNAPSHOT
-
-
- v1_18_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.18.1-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_18_R1/src/main/java/net/artelnatif/nicko/impl/v1_18_R1.java b/v1_18_R1/src/main/java/net/artelnatif/nicko/impl/v1_18_R1.java
deleted file mode 100644
index 1f1b7b7..0000000
--- a/v1_18_R1/src/main/java/net/artelnatif/nicko/impl/v1_18_R1.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.network.chat.IChatBaseComponent;
-import net.minecraft.network.protocol.game.*;
-import net.minecraft.network.syncher.DataWatcher;
-import net.minecraft.network.syncher.DataWatcherObject;
-import net.minecraft.network.syncher.DataWatcherRegistry;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.server.level.EntityPlayer;
-import net.minecraft.world.level.EnumGamemode;
-import net.minecraft.world.level.World;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_18_R1.CraftWorld;
-import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-public class v1_18_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.x().aa();
- final CraftWorld world = entityPlayer.W().getWorld();
- // again, wtf is that
- // f*ck obfuscation
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.W().q_(),
- levelResourceKey, world.getSeed(),
- entityPlayer.d.b(), entityPlayer.d.c(),
- false,
- false,
- false);
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.b.a(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.ai();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.b(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.b.a(destroy);
- onlineEntityPlayer.b.a(spawn);
- }
- onlineEntityPlayer.b.a(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.e, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a);
-
- add.b().clear();
- add.b().add(new PacketPlayOutPlayerInfo.PlayerInfoData(gameProfile,
- player.getPing(),
- EnumGamemode.a(player.getGameMode().ordinal()), IChatBaseComponent.a(profileName)));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.b.a(remove);
- onlineEntityPlayer.b.a(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-}
diff --git a/v1_18_R2/pom.xml b/v1_18_R2/pom.xml
deleted file mode 100644
index 4eb30ad..0000000
--- a/v1_18_R2/pom.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 4.0.0
-
-
- net.artelnatif
- nicko-parent
- 1.0-SNAPSHOT
-
-
- v1_18_R2
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.18.2-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_18_R2/src/main/java/net/artelnatif/nicko/impl/v1_18_R2.java b/v1_18_R2/src/main/java/net/artelnatif/nicko/impl/v1_18_R2.java
deleted file mode 100644
index 1f085f6..0000000
--- a/v1_18_R2/src/main/java/net/artelnatif/nicko/impl/v1_18_R2.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.core.Holder;
-import net.minecraft.network.chat.IChatBaseComponent;
-import net.minecraft.network.protocol.game.*;
-import net.minecraft.network.syncher.DataWatcher;
-import net.minecraft.network.syncher.DataWatcherObject;
-import net.minecraft.network.syncher.DataWatcherRegistry;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.server.level.EntityPlayer;
-import net.minecraft.world.level.EnumGamemode;
-import net.minecraft.world.level.World;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_18_R2.CraftWorld;
-import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-public class v1_18_R2 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.x().aa();
- final CraftWorld world = entityPlayer.s.getWorld();
- // wtf is that ?
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(Holder.a(entityPlayer.s.q_()),
- levelResourceKey, world.getSeed(),
- entityPlayer.d.b(), entityPlayer.d.c(),
- false,
- false,
- false);
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.b.a(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.ai();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.b(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.b.a(destroy);
- onlineEntityPlayer.b.a(spawn);
- }
- onlineEntityPlayer.b.a(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.e, entityPlayer);
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a);
-
- add.b().clear();
- add.b().add(new PacketPlayOutPlayerInfo.PlayerInfoData(gameProfile,
- player.getPing(),
- EnumGamemode.a(player.getGameMode().ordinal()), IChatBaseComponent.a(profileName)));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.b.a(remove);
- onlineEntityPlayer.b.a(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-}
\ No newline at end of file
diff --git a/v1_19_R1/pom.xml b/v1_19_R1/pom.xml
deleted file mode 100644
index ccdb982..0000000
--- a/v1_19_R1/pom.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- 4.0.0
-
-
- net.artelnatif
- nicko-parent
- 1.0-SNAPSHOT
-
-
- v1_19_R1
- 1.0-SNAPSHOT
-
-
-
- org.spigotmc
- spigot
- 1.19.2-R0.1-SNAPSHOT
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_19_R1/src/main/java/net/artelnatif/nicko/impl/v1_19_R1.java b/v1_19_R1/src/main/java/net/artelnatif/nicko/impl/v1_19_R1.java
deleted file mode 100644
index fe98d37..0000000
--- a/v1_19_R1/src/main/java/net/artelnatif/nicko/impl/v1_19_R1.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.network.chat.IChatBaseComponent;
-import net.minecraft.network.protocol.game.*;
-import net.minecraft.network.syncher.DataWatcher;
-import net.minecraft.network.syncher.DataWatcherObject;
-import net.minecraft.network.syncher.DataWatcherRegistry;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.server.level.EntityPlayer;
-import net.minecraft.world.entity.player.ProfilePublicKey;
-import net.minecraft.world.level.EnumGamemode;
-import net.minecraft.world.level.World;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.util.Optional;
-
-public class v1_19_R1 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final ResourceKey levelResourceKey = entityPlayer.x().ab();
- final PacketPlayOutRespawn respawn = new PacketPlayOutRespawn(entityPlayer.x().Z(),
- levelResourceKey, entityPlayer.s.getWorld().getSeed(),
- entityPlayer.d.b(), entityPlayer.d.c(),
- false,
- false,
- false,
- Optional.empty());
-
- final boolean wasFlying = player.isFlying();
- entityPlayer.b.a(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
- final PacketPlayOutEntityDestroy destroy = new PacketPlayOutEntityDestroy(entityPlayer.getBukkitEntity().getEntityId());
- final PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn(entityPlayer);
-
- final DataWatcher dataWatcher = entityPlayer.ai();
- final DataWatcherObject displayedSkinPartDataWatcher = new DataWatcherObject<>(17, DataWatcherRegistry.a);
- dataWatcher.b(displayedSkinPartDataWatcher, (byte) 0x7f);
- final PacketPlayOutEntityMetadata entityMetadata = new PacketPlayOutEntityMetadata(entityPlayer.getBukkitEntity().getEntityId(), dataWatcher, true);
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- if (onlineEntityPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineEntityPlayer.b.a(destroy);
- onlineEntityPlayer.b.a(spawn);
- }
- onlineEntityPlayer.b.a(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final CraftPlayer craftPlayer = (CraftPlayer) player;
- final EntityPlayer entityPlayer = craftPlayer.getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final PacketPlayOutPlayerInfo add = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.a);
- final PacketPlayOutPlayerInfo remove = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.e, entityPlayer);
- // "It's a Surprise Tool That Will Help Us Later!"
- final ProfilePublicKey.a key = remove.b().get(0).e();
-
- add.b().clear();
- add.b().add(new PacketPlayOutPlayerInfo.PlayerInfoData(gameProfile,
- player.getPing(),
- EnumGamemode.a(player.getGameMode().ordinal()),
- IChatBaseComponent.a(profileName),
- key)); // f mojang
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- EntityPlayer onlineEntityPlayer = ((CraftPlayer) online).getHandle();
- onlineEntityPlayer.b.a(remove);
- onlineEntityPlayer.b.a(add);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-}
diff --git a/v1_19_R2/pom.xml b/v1_19_R2/pom.xml
deleted file mode 100644
index 385efc4..0000000
--- a/v1_19_R2/pom.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
- 4.0.0
-
-
- net.artelnatif
- nicko-parent
- 1.0-SNAPSHOT
-
-
- v1_19_R2
- 1.0-SNAPSHOT
-
-
-
-
- net.md-5
- specialsource-maven-plugin
- 1.2.4
-
-
- package
-
- remap
-
- remap-obf
-
- org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:txt:maps-mojang
- true
- org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-mojang
- true
- remapped-obf
-
-
-
- package
-
- remap
-
- remap-spigot
-
- ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
- org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:csrg:maps-spigot
- org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-obf
-
-
-
-
-
-
-
-
-
- org.spigotmc
- spigot
- 1.19.3-R0.1-SNAPSHOT
- remapped-mojang
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_19_R2/src/main/java/net/artelnatif/nicko/impl/v1_19_R2.java b/v1_19_R2/src/main/java/net/artelnatif/nicko/impl/v1_19_R2.java
deleted file mode 100644
index 4059960..0000000
--- a/v1_19_R2/src/main/java/net/artelnatif/nicko/impl/v1_19_R2.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.network.chat.Component;
-import net.minecraft.network.chat.RemoteChatSession;
-import net.minecraft.network.protocol.game.*;
-import net.minecraft.network.syncher.EntityDataAccessor;
-import net.minecraft.network.syncher.EntityDataSerializers;
-import net.minecraft.network.syncher.SynchedEntityData;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.world.entity.player.ProfilePublicKey;
-import net.minecraft.world.level.Level;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Field;
-import java.util.*;
-
-public class v1_19_R2 implements Internals {
- @Override
- public void updateSelf(Player player) {
- final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
- final ServerLevel level = serverPlayer.getLevel();
- final ResourceKey levelResourceKey = serverPlayer.getLevel().dimension();
- final ClientboundRespawnPacket respawn = new ClientboundRespawnPacket(serverPlayer.level.dimensionTypeId(),
- levelResourceKey, level.getWorld().getSeed(),
- serverPlayer.gameMode.getGameModeForPlayer(), serverPlayer.gameMode.getPreviousGameModeForPlayer(),
- level.isDebug(),
- level.isFlat(),
- (byte) 0x00,
- Optional.empty());
-
- final boolean wasFlying = player.isFlying();
- serverPlayer.connection.send(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
- final ClientboundRemoveEntitiesPacket remove = new ClientboundRemoveEntitiesPacket(serverPlayer.getBukkitEntity().getEntityId());
- final ClientboundAddEntityPacket add = new ClientboundAddEntityPacket(serverPlayer);
-
- final SynchedEntityData entityData = serverPlayer.getEntityData();
- final EntityDataAccessor skinPartAccessor = new EntityDataAccessor<>(17, EntityDataSerializers.BYTE);
- entityData.set(skinPartAccessor, (byte) 0x7f);
- final ClientboundSetEntityDataPacket entityMetadata = new ClientboundSetEntityDataPacket(serverPlayer.getBukkitEntity().getEntityId(), entityData.getNonDefaultValues());
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- final ServerPlayer onlineServerPlayer = ((CraftPlayer) online).getHandle();
- if (onlineServerPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineServerPlayer.connection.send(remove);
- onlineServerPlayer.connection.send(add);
- }
- onlineServerPlayer.connection.send(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final ClientboundPlayerInfoUpdatePacket init = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(Collections.singletonList(serverPlayer));
- final ClientboundPlayerInfoRemovePacket remove = new ClientboundPlayerInfoRemovePacket(Collections.singletonList(player.getUniqueId()));
-
- RemoteChatSession chatSession;
- if (serverPlayer.getChatSession() == null) {
- NickoBukkit.getInstance().getLogger().warning("Chat Session of " + serverPlayer.displayName + " is null!");
- NickoBukkit.getInstance().getLogger().warning("If your server is in offline mode/under BungeeCord you can safely ignore this message.");
- chatSession = null;
- } else {
- final UUID uuid = serverPlayer.getChatSession().sessionId();
- final ProfilePublicKey ppk = serverPlayer.getChatSession().profilePublicKey();
- chatSession = new RemoteChatSession(uuid, ppk);
- }
-
- spoofPlayerInfoPacket(init, Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.Entry(
- player.getUniqueId(),
- gameProfile,
- true,
- serverPlayer.latency,
- serverPlayer.gameMode.getGameModeForPlayer(),
- Component.literal(profileName),
- chatSession == null ? null : chatSession.asData()
- )));
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- final ServerPlayer onlinePlayer = ((CraftPlayer) online).getHandle();
- onlinePlayer.connection.send(remove);
- onlinePlayer.connection.send(init);
- });
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-}
diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml
deleted file mode 100644
index eefd19d..0000000
--- a/v1_19_R3/pom.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
- 4.0.0
-
-
- net.artelnatif
- nicko-parent
- 1.0-SNAPSHOT
-
-
- v1_19_R3
- 1.0-SNAPSHOT
-
-
-
-
- net.md-5
- specialsource-maven-plugin
- 1.2.4
-
-
- package
-
- remap
-
- remap-obf
-
- org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:txt:maps-mojang
- true
- org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-mojang
- true
- remapped-obf
-
-
-
- package
-
- remap
-
- remap-spigot
-
- ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
- org.spigotmc:minecraft-server:1.19.4-R0.1-SNAPSHOT:csrg:maps-spigot
- org.spigotmc:spigot:1.19.4-R0.1-SNAPSHOT:jar:remapped-obf
-
-
-
-
-
-
-
-
-
- org.spigotmc
- spigot
- 1.19.4-R0.1-SNAPSHOT
- remapped-mojang
- provided
-
-
- net.artelnatif
- core
- 1.0-SNAPSHOT
-
-
-
\ No newline at end of file
diff --git a/v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java b/v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java
deleted file mode 100644
index d0ef0eb..0000000
--- a/v1_19_R3/src/main/java/net/artelnatif/nicko/impl/v1_19_R3.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package net.artelnatif.nicko.impl;
-
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.properties.Property;
-import com.mojang.authlib.properties.PropertyMap;
-import net.artelnatif.nicko.NickoBukkit;
-import net.artelnatif.nicko.disguise.ActionResult;
-import net.artelnatif.nicko.disguise.NickoProfile;
-import net.artelnatif.nicko.mojang.MojangSkin;
-import net.minecraft.network.chat.Component;
-import net.minecraft.network.chat.RemoteChatSession;
-import net.minecraft.network.protocol.game.*;
-import net.minecraft.network.syncher.EntityDataAccessor;
-import net.minecraft.network.syncher.EntityDataSerializers;
-import net.minecraft.network.syncher.SynchedEntityData;
-import net.minecraft.resources.ResourceKey;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.world.entity.player.ProfilePublicKey;
-import net.minecraft.world.level.Level;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
-import org.bukkit.entity.Player;
-import org.bukkit.event.player.PlayerTeleportEvent;
-
-import java.lang.reflect.Field;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.logging.Logger;
-
-public class v1_19_R3 implements Internals {
- final Logger logger = Bukkit.getLogger();
-
- @Override
- public void updateSelf(Player player) {
- final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
- final ServerLevel level = serverPlayer.getLevel();
- final ResourceKey levelResourceKey = serverPlayer.getLevel().dimension();
- final ClientboundRespawnPacket respawn = new ClientboundRespawnPacket(serverPlayer.level.dimensionTypeId(),
- levelResourceKey, level.getWorld().getSeed(),
- serverPlayer.gameMode.getGameModeForPlayer(), serverPlayer.gameMode.getPreviousGameModeForPlayer(),
- level.isDebug(),
- level.isFlat(),
- (byte) 0x00,
- Optional.empty());
-
- final boolean wasFlying = player.isFlying();
- serverPlayer.connection.send(respawn);
- player.setFlying(wasFlying);
- player.teleport(player.getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
- player.updateInventory();
- }
-
- @Override
- public void updateOthers(Player player) {
- final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
-
- final ClientboundRemoveEntitiesPacket remove = new ClientboundRemoveEntitiesPacket(serverPlayer.getBukkitEntity().getEntityId());
- final ClientboundAddEntityPacket add = new ClientboundAddEntityPacket(serverPlayer);
-
- final SynchedEntityData entityData = serverPlayer.getEntityData();
- final EntityDataAccessor skinPartAccessor = new EntityDataAccessor<>(17, EntityDataSerializers.BYTE);
- entityData.set(skinPartAccessor, (byte) 0x7f);
- final ClientboundSetEntityDataPacket entityMetadata = new ClientboundSetEntityDataPacket(serverPlayer.getBukkitEntity().getEntityId(), entityData.getNonDefaultValues());
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- final ServerPlayer onlineServerPlayer = ((CraftPlayer) online).getHandle();
- if (onlineServerPlayer.getBukkitEntity().getUniqueId() != player.getUniqueId()) {
- onlineServerPlayer.connection.send(remove);
- onlineServerPlayer.connection.send(add);
- }
- onlineServerPlayer.connection.send(entityMetadata);
- });
- }
-
- @Override
- public ActionResult updateProfile(Player player, NickoProfile profile, boolean skinChange, boolean reset) {
- final boolean changeOnlyName = profile.getSkin() != null && !profile.getSkin().equalsIgnoreCase(player.getName());
- final String profileName = profile.getName() == null ? player.getName() : profile.getName();
-
- final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
- final GameProfile gameProfile = new GameProfile(player.getUniqueId(), profileName);
-
- if (skinChange || changeOnlyName) {
- final ActionResult skinFetch = fetchSkinTextures(profile, reset);
- if (!skinFetch.isError()) {
- final MojangSkin skin = skinFetch.getResult();
- final PropertyMap properties = gameProfile.getProperties();
- properties.removeAll("textures");
- properties.put("textures", new Property("textures", skin.getValue(), skin.getSignature()));
- updateSelf(player);
- }
- }
-
- final ClientboundPlayerInfoUpdatePacket init = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(Collections.singletonList(serverPlayer));
- final ClientboundPlayerInfoRemovePacket remove = new ClientboundPlayerInfoRemovePacket(Collections.singletonList(player.getUniqueId()));
-
- RemoteChatSession chatSession;
- if (serverPlayer.getChatSession() == null) {
- NickoBukkit.getInstance().getLogger().warning("Chat Session of " + serverPlayer.displayName + " is null!");
- NickoBukkit.getInstance().getLogger().warning("If your server is in offline mode/under BungeeCord you can safely ignore this message.");
- chatSession = null;
- } else {
- final UUID uuid = serverPlayer.getChatSession().sessionId();
- final ProfilePublicKey ppk = serverPlayer.getChatSession().profilePublicKey();
- chatSession = new RemoteChatSession(uuid, ppk);
- }
-
- spoofPlayerInfoPacket(init, Collections.singletonList(new ClientboundPlayerInfoUpdatePacket.Entry(
- player.getUniqueId(),
- gameProfile,
- true,
- serverPlayer.latency,
- serverPlayer.gameMode.getGameModeForPlayer(),
- Component.literal(profileName),
- chatSession == null ? null : chatSession.asData()
- )));
-
-
- Bukkit.getOnlinePlayers().forEach(online -> {
- final ServerPlayer onlinePlayer = ((CraftPlayer) online).getHandle();
- onlinePlayer.connection.send(remove);
- onlinePlayer.connection.send(init);
- });
- // TODO: 3/17/23 Update signature to avoid duplicate for loop
- updateOthers(player);
- return new ActionResult<>();
- }
-
- private void spoofPlayerInfoPacket(Object object, Object newValue) {
- try {
- final Field field = object.getClass().getDeclaredField("b");
- field.setAccessible(true);
- field.set(object, newValue);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- NickoBukkit.getInstance().getLogger().warning("Unable to spoof packet, that's bad! (" + e.getMessage() + ")");
- }
- }
-}