9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-25 01:49:24 +00:00

Compare commits

...

57 Commits

Author SHA1 Message Date
LoJoSho
6e94d74990 removed Citizens hook
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-21 11:09:56 -05:00
LoJoSho
5e3edd472c Revert previous commit
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-04 14:44:39 -05:00
LoJoSho
791fe53c48 NMS Test
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-04 14:32:08 -05:00
LoJoSho
c9f7762a26 work on ME 3.0
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-03 21:38:22 -05:00
LoJoSho
1be95c78c2 Moved around code
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-03 20:24:26 -05:00
LoJoSho
2be06e3ad9 Debug Logging for Balloons
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-10-03 20:24:12 -05:00
LoJoSho
d4bf6f256b Equipment no longer always sends full slots
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-30 12:29:10 -05:00
LoJoSho
5ffe39cdba Remove debug message
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-25 19:39:25 -05:00
LoJoSho
e6c81f8d1e Merge remote-tracking branch 'origin/plib_switch' into plib_switch 2022-09-25 19:36:23 -05:00
LoJoSho
0378b98967 Packet Overhaul, ME 3.0 Work, Teleport to last location config option
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-25 19:36:03 -05:00
lucian929
a26edbfc9c Add new cosmetics 2022-09-24 12:49:57 -04:00
lucian929
19e8a3bf10 Disable first person backpacks temporarily 2022-09-19 10:07:38 -04:00
LoJoSho
b8aefbacdb version bump (1.12.0-BETA-5)
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-10 21:26:15 -05:00
LoJoSho
7a29aa8927 Disabled Model Engine integration
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-10 21:23:51 -05:00
LoJoSho
482aec27f1 Fix for client disconnect as NPC name was >16 characters
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-10 21:22:52 -05:00
LoJoSho
007e5487e6 Added pumpkin option for wardrobe
Signed-off-by: LoJoSho <contact@lojosho.com>
2022-09-05 20:59:59 -05:00
LoJoSho
e7f077af7a Merge remote-tracking branch 'origin/plib_switch' into plib_switch 2022-09-05 20:26:28 -05:00
LoJoSho
99b1afd15c Changed info packet to be sent earlier 2022-09-05 20:26:10 -05:00
lucian929
3f5acde838 Update libraries
Signed-off-by: lucian929 <lucianfp27091@gmail.com>
2022-09-01 10:49:35 -04:00
LoJoSho
2676505c9a Version Bump (Beta-4) 2022-08-29 19:26:21 -05:00
LoJoSho
f5d1a09d28 Gui Opening + Skins in Wardrobe 2022-08-29 19:24:18 -05:00
LoJoSho
1b9e2ac531 Wardrobe Works! 2022-08-29 18:39:34 -05:00
LoJoSho
b005614881 Bundle of small changes 2022-08-29 14:16:43 -05:00
lucian929
a41fb7df2b Beta-3 2022-08-19 16:23:33 -04:00
LoJoSho
e0fbbc7f76 Fixed issue with armor not showing 2022-08-19 15:21:47 -05:00
LoJoSho
cb09da91fe Removed boolean from packet 2022-08-19 15:21:30 -05:00
LoJoSho
cd7ed29522 remove line 2022-08-19 15:20:29 -05:00
LoJoSho
f5a7c2f9f0 Byte mask apply 2022-08-18 17:47:53 -05:00
LoJoSho
6af8e13dab Removed Debug Messages 2022-08-18 17:36:52 -05:00
LoJoSho
e3f081f1c9 Version Bump (Beta-2) 2022-08-18 17:35:48 -05:00
LoJoSho
c7ba2f179a Update Citizens 2022-08-18 17:35:30 -05:00
LoJoSho
8f012f6c97 Fixed duplicate entity ids causing visual issues 2022-08-18 17:35:18 -05:00
LoJoSho
e95b30131c Bundle of changes 2022-08-18 15:02:21 -05:00
LoJoSho
2dc068a938 Bundle of changes 2022-08-15 17:59:53 -05:00
lucian929
7bdc122cb1 Bump version number (initial beta) 2022-08-15 16:31:09 -04:00
lucian929
a3d57af18d Merge pull request #31 from LoJoSho/lojo_dev
Experimental ProtocolLib Switch
2022-08-15 16:25:20 -04:00
LoJoSho
235c0a9307 Cosmetic Fixes 2022-08-15 15:17:16 -05:00
LoJoSho
4d7e565c23 Latest Commit 2022-08-12 14:34:54 -05:00
LoJoSho
57d3110740 It works! 2022-08-12 09:49:31 -05:00
LoJoSho
61e226b826 Compiling without PacketEvents 2022-08-09 22:16:35 -05:00
LoJoSho
bd7b045c0f Initial ProtocolLib Testing 2022-08-08 13:05:50 -05:00
LoJoSho
1ce28a9f66 Uncommented ProtocolLib 2022-08-08 13:05:04 -05:00
lucian929
70c2b79b6c Bump version number 2022-07-25 18:54:27 -04:00
Boy0000
39d485ddfe remove broadcast (#29) 2022-07-26 00:53:01 +02:00
lucian929
548a6bf4ec Merge pull request #28 from HibiscusMC/1.19_fix
1.19 fix
2022-07-25 18:50:24 -04:00
Boy
fb15919f52 update non-existing packet 2022-07-26 00:45:26 +02:00
lucian929
9a5923bb7d Merge remote-tracking branch 'origin/master' 2022-07-20 18:33:40 -04:00
lucian929
02239396f0 Changes to build.gradle.kts for MEG (temporary fix) 2022-07-20 18:33:20 -04:00
lucian929
942d48adf8 Merge pull request #26 from HibiscusMC/copyjar_task
add copyjar task
2022-07-17 18:06:01 -04:00
Boy
99ae2b765a add copyjar task 2022-07-18 00:04:13 +02:00
lucian929
6b59ba88a5 Bump version number 2022-07-11 13:15:12 -04:00
Fisher2911
4d7dff885a Merge remote-tracking branch 'origin/master' 2022-07-11 13:14:07 -04:00
Fisher2911
f4bc6f1bc3 Fixed particle amounts not working 2022-07-11 13:13:54 -04:00
lucian929
938dfe677d Fix mistake in config 2022-07-08 20:48:08 -04:00
Fisher2911
1c30924410 Merge remote-tracking branch 'origin/master' 2022-07-08 20:26:38 -04:00
lucian929
bd731c8b6b bump version number (1.11.0)! 2022-07-08 20:24:24 -04:00
lucian929
41f4f830d1 Update default configs 2022-07-08 20:22:50 -04:00
41 changed files with 3552 additions and 1117 deletions

View File

@@ -7,7 +7,7 @@ plugins {
}
group = "io.github.fisher2911"
version = "1.11.0-BETA-4"
version = "1.12.0-BETA-5"
description = "Intuitive, easy-to-use cosmetics plugin, designed for servers using resource packs.\n"
repositories {
@@ -21,7 +21,13 @@ repositories {
maven("https://mvnrepository.com/artifact/com.zaxxer/HikariCP")
maven("https://repo.jeff-media.de/maven2/")
maven("https://repo.citizensnpcs.co")
maven("https://mvn.lumine.io/repository/maven-public")
//maven("https://mvn.lumine.io/repository/maven-public")
maven {
url = uri("https://mvn.lumine.io/repository/maven-public")
metadataSources {
artifact()
}
}
maven("https://jitpack.io/")
}
@@ -32,22 +38,22 @@ dependencies {
// implementation(project(":nms"))
compileOnly("com.mojang:authlib:1.5.25")
compileOnly("org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:22.0.0")
// compileOnly("com.comphenix.protocol:ProtocolLib:4.7.0")
compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0-SNAPSHOT")
compileOnly("me.clip:placeholderapi:2.11.1")
compileOnly("com.github.oraxen:oraxen:-SNAPSHOT")
compileOnly("com.github.LoneDev6:API-ItemsAdder:2.5.4")
compileOnly("net.citizensnpcs:citizens-main:2.0.29-SNAPSHOT")
compileOnly("com.ticxo.modelengine:api:R2.5.0:")
compileOnly("com.github.retrooper.packetevents:spigot:2.0-SNAPSHOT")
implementation("net.kyori:adventure-api:4.10.0")
implementation ("net.kyori:adventure-text-minimessage:4.10.0-SNAPSHOT")
implementation("net.kyori:adventure-platform-bukkit:4.0.1")
implementation("dev.triumphteam:triumph-gui:3.1.2")
compileOnly("net.citizensnpcs:citizens-main:2.0.30-SNAPSHOT")
compileOnly("com.ticxo.modelengine:api:R3.0.0")
//compileOnly("com.github.retrooper.packetevents:spigot:2.0-SNAPSHOT")
implementation("net.kyori:adventure-api:4.11.0")
implementation ("net.kyori:adventure-text-minimessage:4.11.0")
implementation("net.kyori:adventure-platform-bukkit:4.1.2")
implementation("dev.triumphteam:triumph-gui:3.1.3")
implementation("me.mattstudios.utils:matt-framework:1.4.6")
implementation("org.spongepowered:configurate-yaml:4.1.2")
implementation("org.bstats:bstats-bukkit:2.2.1")
implementation("com.zaxxer:HikariCP:5.0.0")
implementation("org.bstats:bstats-bukkit:3.0.0")
implementation("com.zaxxer:HikariCP:5.0.1")
implementation("com.j256.ormlite:ormlite-jdbc:6.1")
implementation("com.j256.ormlite:ormlite-core:6.1")
}
@@ -105,7 +111,7 @@ bukkit {
name = "HMCCosmetics"
authors = listOf("MasterOfTheFish")
softDepend = listOf("Multiverse", "PlaceholderAPI", "Oraxen", "ItemsAdder", "Citizens", "ModelEngine")
depend = listOf("packetevents")
depend = listOf("ProtocolLib")
permissions {
register("hmccosmetics.cmd.default") {
default = BukkitPluginDescription.Permission.Default.OP
@@ -141,3 +147,22 @@ bukkit {
}
}
}
val copyJar: String? by project
val pluginPath = project.findProperty("hibiscusmc_plugin_path")
if(copyJar != "false" && pluginPath != null) {
tasks {
register<Copy>("copyJar") {
from(findByName("reobfJar") ?: findByName("shadowJar") ?: findByName("jar"))
into(pluginPath)
doLast {
println("Copied to plugin directory $pluginPath")
}
}
named<DefaultTask>("build") {
dependsOn("copyJar")
}
}
}

View File

@@ -1,6 +1,7 @@
package io.github.fisher2911.hmccosmetics;
import com.github.retrooper.packetevents.PacketEvents;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import io.github.fisher2911.hmccosmetics.command.CosmeticsCommand;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;
import io.github.fisher2911.hmccosmetics.config.Settings;
@@ -24,6 +25,7 @@ import io.github.fisher2911.hmccosmetics.listener.WardrobeListener;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.task.TaskManager;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import me.mattstudios.mf.base.CommandManager;
@@ -57,6 +59,7 @@ public class HMCCosmetics extends JavaPlugin {
private Database database;
private BukkitTask saveTask;
private ProtocolManager manager;
/* // commented because PacketEvents is no longer shaded
@Override
@@ -77,6 +80,7 @@ public class HMCCosmetics extends JavaPlugin {
this.cosmeticManager = new CosmeticManager(new HashMap<>(), new HashMap<>(), new HashMap<>());
this.cosmeticsMenu = new CosmeticsMenu(this);
this.tokenLoader = new TokenLoader(this);
this.manager = ProtocolLibrary.getProtocolManager();
this.userManager.startTeleportTask();
@@ -86,6 +90,7 @@ public class HMCCosmetics extends JavaPlugin {
exception.printStackTrace();
}
PacketManager.setupPackets();
this.registerCommands();
this.registerListeners();
@@ -107,7 +112,7 @@ public class HMCCosmetics extends JavaPlugin {
@Override
public void onDisable() {
PacketEvents.getAPI().terminate();
//PacketEvents.getAPI().terminate();
this.saveTask.cancel();
this.database.saveAll();
this.messageHandler.close();
@@ -241,6 +246,9 @@ public class HMCCosmetics extends JavaPlugin {
public Database getDatabase() {
return database;
}
public ProtocolManager getProtocolManager() {
return manager;
}
}

View File

@@ -1,17 +1,17 @@
package io.github.fisher2911.hmccosmetics.config;
import com.github.retrooper.packetevents.protocol.sound.SoundCategory;
import com.comphenix.protocol.wrappers.EnumWrappers;
import net.minecraft.server.v1_16_R3.MinecraftKey;
import org.bukkit.entity.Player;
public class SoundData {
private final String name;
private final SoundCategory soundCategory;
private final EnumWrappers.SoundCategory soundCategory;
private final float volume;
private final float pitch;
public SoundData(final String name, final SoundCategory soundCategory, final float volume, final float pitch) {
public SoundData(final String name, final EnumWrappers.SoundCategory soundCategory, final float volume, final float pitch) {
this.name = name;
this.soundCategory = soundCategory;
this.volume = volume;
@@ -30,7 +30,7 @@ public class SoundData {
return pitch;
}
public SoundCategory getSoundCategory() {
public EnumWrappers.SoundCategory getSoundCategory() {
return soundCategory;
}

View File

@@ -1,6 +1,6 @@
package io.github.fisher2911.hmccosmetics.config;
import com.github.retrooper.packetevents.protocol.sound.SoundCategory;
import com.comphenix.protocol.wrappers.EnumWrappers;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.serialize.SerializationException;
@@ -37,7 +37,7 @@ public class SoundSerializer implements TypeSerializer<SoundData> {
} else {
soundData = new SoundData(
soundName,
SoundCategory.valueOf(category),
EnumWrappers.SoundCategory.valueOf(category),
volume,
pitch
);

View File

@@ -27,6 +27,8 @@ public class WardrobeSettings {
private static final String STATIC_LOCATION_PATH = "wardrobe-location";
private static final String VIEWER_LOCATION_PATH = "viewer-location";
private static final String LEAVE_LOCATION_PATH = "leave-location";
private static final String EQUIP_PUMPKIN_WARDROBE = "equip-pumpkin";
private static final String RETURN_LAST_LOCATION = "return-last-location";
private final HMCCosmetics plugin;
@@ -39,6 +41,8 @@ public class WardrobeSettings {
private int spawnDelay;
private int despawnDelay;
private boolean applyCosmeticsOnClose;
private boolean equipPumpkin;
private boolean returnLastLocation;
private SoundData openSound;
private SoundData closeSound;
private Location wardrobeLocation;
@@ -71,6 +75,8 @@ public class WardrobeSettings {
this.spawnDelay = source.node(SPAWN_DELAY_PATH).getInt();
this.despawnDelay = source.node(DESPAWN_DELAY_PATH).getInt();
this.applyCosmeticsOnClose = source.node(APPLY_COSMETICS_ON_CLOSE).getBoolean();
this.equipPumpkin = source.node(EQUIP_PUMPKIN_WARDROBE).getBoolean();
this.returnLastLocation = source.node(RETURN_LAST_LOCATION).getBoolean();
this.openSound = source.node(OPEN_SOUND).get(SoundData.class);
this.closeSound = source.node(CLOSE_SOUND).get(SoundData.class);
this.wardrobeLocation = source.node(STATIC_LOCATION_PATH).get(Location.class);
@@ -116,6 +122,12 @@ public class WardrobeSettings {
public boolean isApplyCosmeticsOnClose() {
return applyCosmeticsOnClose;
}
public boolean isEquipPumpkin() {
return equipPumpkin;
}
public boolean isReturnLastLocation() {
return returnLastLocation;
}
public Location getWardrobeLocation() {
return this.wardrobeLocation.clone();

View File

@@ -96,6 +96,7 @@ public class CosmeticManager {
public void load() {
this.clearItems();
this.backpackParticleCounts.clear();
try {
final File file = ITEMS_PATH.toFile();
if (!file.exists()) {
@@ -115,7 +116,7 @@ public class CosmeticManager {
if (item instanceof ArmorItem armorItem) {
armorItem.setAction(null);
if (armorItem.getType() == ArmorItem.Type.SELF_BACKPACK) {
final int particleCount = node.node(PARTICLE_COUNT).getInt(0);
final int particleCount = node.node(PARTICLE_COUNT).getInt(5);
this.backpackParticleCounts.put(armorItem.getId(), particleCount);
}
this.armorItemMap.put(armorItem.getId(), armorItem);

View File

@@ -16,13 +16,15 @@ import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class Database {
@@ -234,6 +236,7 @@ public class Database {
}
public static int getNextEntityId() {
return SpigotReflectionUtil.generateEntityId();
Random random = new Random();
return random.nextInt(999999);
}
}

View File

@@ -348,18 +348,6 @@ public class ArmorItem extends WrappedGuiItem {
};
}
@Nullable
public static Type fromPacketSlot(final com.github.retrooper.packetevents.protocol.player.EquipmentSlot slot) {
return switch (slot) {
case HELMET -> Type.HAT;
case CHEST_PLATE -> Type.CHEST_PLATE;
case LEGGINGS -> Type.PANTS;
case BOOTS -> Type.BOOTS;
case OFF_HAND -> Type.OFF_HAND;
default -> null;
};
}
@Nullable
public static Type fromEquipmentSlot(final EquipmentSlot slot) {
for (final Type type : values()) {

View File

@@ -55,13 +55,19 @@ public class HookManager {
this.listeners.add(itemsAdderHook);
}
if (pluginManager.getPlugin("Citizens") != null) {
this.citizensHook = null;
/*
this.registerHook(citizensHook.getClass());
this.listeners.add(citizensHook);
this.citizensHook = citizensHook;
this.plugin.getLogger().info("Successfully Hooked into Citizens!");
*/
} else {
this.citizensHook = null;
}
if (pluginManager.getPlugin("ModelEngine") != null) {
this.plugin.getLogger().info("ModelEngine has been detected and has been enabled.");
// 3.0 Model Engine Beta
final ModelEngineHook modelEngineHook = new ModelEngineHook();
this.registerHook(modelEngineHook.getClass());
this.modelEngineHook = modelEngineHook;

View File

@@ -3,121 +3,105 @@ package io.github.fisher2911.hmccosmetics.hook.entity;
import com.ticxo.modelengine.api.ModelEngineAPI;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class BalloonEntity {
private final int balloonID;
private final MEGEntity megEntity;
// private final UUID uuid;
// private final int entityId;
// private EntityType entityType;
// private Vector velocity;
// private Location location;
// private boolean alive;
public BalloonEntity(final UUID uuid, final int entityId, final EntityType entityType, final Vector velocity, final Location location, final boolean alive) {
this.megEntity = new MEGEntity(uuid, entityId, entityType, velocity, location, alive);
// this.uuid = uuid;
// this.entityId = entityId;
// this.entityType = entityType;
// this.velocity = velocity;
// this.location = location;
// this.alive = alive;
// this.megEntity = new MEGEntity(this);
public BalloonEntity(int balloonID, Location location) {
this.balloonID = balloonID;
this.megEntity = new MEGEntity(UUID.randomUUID(), balloonID, new Vector(0, 0, 0), location, false);
}
public BalloonEntity(final UUID uuid, final int entityId, final EntityType entityType) {
// this.uuid = uuid;
// this.entityId = entityId;
// this.entityType = entityType;
this.megEntity = new MEGEntity(uuid, entityId, entityType);
public void updateModel() {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (model == null) return;
if (model.getBase() instanceof final MEGEntity e) e.update(this);
}
public UUID getUuid() {
return this.megEntity.getUuid();
public void spawnModel(final String id) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Attempting Spawning");
if (ModelEngineAPI.api.getModelRegistry().getBlueprint(id) == null) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().warning("Invalid Model Engine Blueprint " + id);
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().warning("Possible Blueprints" + ModelEngineAPI.api.getModelRegistry().getAllBlueprintId());
return;
}
final ActiveModel model = ModelEngineAPI.api.createActiveModelImpl(ModelEngineAPI.getBlueprint(id));
ModeledEntity modeledEntity = ModelEngineAPI.api.createModeledEntityImpl(megEntity);
modeledEntity.addModel(model, false);
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Spawned Model");
}
public int getEntityId() {
return this.megEntity.getEntityId();
public void remove() {
final ModeledEntity entity = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (entity == null) return;
for (final Player player : entity.getRangeManager().getPlayerInRange()) {
entity.hideFromPlayer(player);
}
//ModelEngineAPI.removeModeledEntity(megEntity.getUniqueId());
entity.destroy();
}
public EntityType getType() {
return this.megEntity.getType();
public void addPlayerToModel(final Player player, final String id) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (model == null) {
this.spawnModel(id);
return;
}
if (megEntity.getRangeManager().getPlayerInRange().contains(player)) return;
model.showToPlayer(player);
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Added " + player.getName() + " to " + id);
}
public Vector getVelocity() {
return this.megEntity.getVelocity();
public void removePlayerFromModel(final Player player) {
final ModeledEntity model = ModelEngineAPI.api.getModeledEntity(megEntity.getUniqueId());
if (model == null) return;
model.hideFromPlayer(player);
}
public void setVelocity(final Vector velocity) {
this.megEntity.setVelocity(velocity);
public int getBalloonID() {
return balloonID;
}
public UUID getUniqueID() {
return megEntity.getUniqueId();
}
public Location getLocation() {
return this.megEntity.getLocation();
}
public void setLocation(final Location location) {
this.megEntity.setLocation(location);
}
public boolean isAlive() {
return this.megEntity.isAlive();
}
public void setAlive(final boolean alive) {
public void setLocation(Location location) {
this.megEntity.setLocation(location);
}
public void setVelocity(Vector vector) {
this.megEntity.setVelocity(vector);
}
public void setAlive(boolean alive) {
this.megEntity.setAlive(alive);
}
public void updateModel() {
final ModeledEntity model = ModelEngineAPI.getModeledEntity(this.getUuid());
if (model == null) return;
if (model.getEntity() instanceof final MEGEntity e) e.update(this);
}
public void spawnModel(final String id) {
if (ModelEngineAPI.getModeledEntity(this.getUuid()) != null) return;
final ActiveModel model = ModelEngineAPI.createActiveModel(id);
ModeledEntity modeledEntity = ModelEngineAPI.api.getModelManager().createModeledEntity(this.megEntity);
modeledEntity.addActiveModel(model);
}
public void addPlayerToModel(final Player player, final String id) {
final ModeledEntity model = ModelEngineAPI.getModeledEntity(this.getUuid());
if (model == null) {
this.spawnModel(id);
return;
}
if (model.getPlayerInRange().contains(player)) return;
model.addPlayerAsync(player);
}
public void removePlayerFromModel(final Player player) {
final ModeledEntity model = ModelEngineAPI.getModeledEntity(this.getUuid());
if (model == null) return;
model.removePlayerAsync(player);
}
public void remove() {
final ModeledEntity entity = ModelEngineAPI.getModeledEntity(this.getUuid());
if (entity == null) return;
for (final Player player : entity.getPlayerInRange()) {
entity.removePlayerAsync(player);
}
ModelEngineAPI.api.getModelManager().removeModeledEntity(this.getUuid());
entity.getEntity().remove();
}
}

View File

@@ -1,67 +1,64 @@
package io.github.fisher2911.hmccosmetics.hook.entity;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import com.ticxo.modelengine.api.model.base.BaseEntity;
import com.ticxo.modelengine.api.model.base.EntityData;
import com.ticxo.modelengine.api.entity.BaseEntity;
import com.ticxo.modelengine.api.generator.Hitbox;
import com.ticxo.modelengine.api.model.IModel;
import com.ticxo.modelengine.api.nms.entity.impl.DefaultBodyRotationController;
import com.ticxo.modelengine.api.nms.entity.impl.EmptyRangeManager;
import com.ticxo.modelengine.api.nms.entity.impl.ManualRangeManager;
import com.ticxo.modelengine.api.nms.entity.wrapper.BodyRotationController;
import com.ticxo.modelengine.api.nms.entity.wrapper.LookController;
import com.ticxo.modelengine.api.nms.entity.wrapper.MoveController;
import com.ticxo.modelengine.api.nms.entity.wrapper.RangeManager;
import com.ticxo.modelengine.api.nms.world.IDamageSource;
import com.ticxo.modelengine.api.utils.data.EntityData;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class MEGEntity implements BaseEntity<MEGEntity> {
public class MEGEntity implements BaseEntity {
private final UUID uuid;
private final int entityId;
private final EntityType entityType;
private Vector velocity = new Vector(0, 0, 0);
private Location location;
private boolean alive;
private BodyRotationController rotationController;
private List<Entity> passengers;
private RangeManager rangeManager;
public MEGEntity(final BalloonEntity entity) {
this.uuid = entity.getUuid();
this.entityId = entity.getEntityId();
this.entityType = entity.getType();
this.velocity = entity.getVelocity();
this.location = entity.getLocation();
this.alive = entity.isAlive();
}
protected MEGEntity(final UUID uuid, final int entityId, final EntityType entityType, final Vector velocity, final Location location, final boolean alive) {
protected MEGEntity(final UUID uuid, final int entityId, final Vector velocity, final Location location, final boolean alive) {
this.uuid = uuid;
this.entityId = entityId;
this.entityType = entityType;
this.velocity = velocity;
this.location = location;
this.alive = alive;
this.rotationController = new DefaultBodyRotationController(this);
this.passengers = new ArrayList<>();
this.rangeManager = new EmptyRangeManager();
this.rangeManager.setRenderDistance(16);
}
protected MEGEntity(final UUID uuid, final int entityId, final EntityType entityType) {
protected MEGEntity(final UUID uuid, final int entityId) {
this.uuid = uuid;
this.entityId = entityId;
this.entityType = entityType;
this.alive = false;
}
public void update(final BalloonEntity entity) {
this.velocity = entity.getVelocity();
this.velocity = entity.getLocation().toVector();
this.location = entity.getLocation();
this.alive = entity.isAlive();
}
public UUID getUuid() {
return uuid;
}
public void setVelocity(final Vector velocity) {
this.velocity = velocity;
}
@@ -82,54 +79,96 @@ public class MEGEntity implements BaseEntity<MEGEntity> {
return entityData;
}
final EntityData entityData = new EntityData();
@Override
public MEGEntity getBase() {
return this;
public Object getOriginal() {
return null;
}
@Override
public Location getLocation() {
return this.location;
public MoveController wrapMoveControl() {
return null;
}
@Override
public Vector getVelocity() {
return velocity;
public LookController wrapLookControl() {
return null;
}
@Override
public boolean isOnGround() {
public BodyRotationController wrapBodyRotationControl() {
return this.rotationController;
}
@Override
public void wrapNavigation() {
}
@Override
public RangeManager wrapRangeManager(IModel model) {
return new ManualRangeManager(this, model);
}
@Override
public RangeManager getRangeManager() {
if (this.rangeManager == null) {
RangeManager rangeMan = new EmptyRangeManager();
rangeMan.setRenderDistance(16);
return rangeMan;
}
return this.rangeManager;
}
@Override
public boolean onHurt(IDamageSource damageSource, float damage) {
return false;
}
@Override
public World getWorld() {
return this.location.getWorld();
public void onInteract(Player player, EquipmentSlot hand) {
}
@Override
public List<Entity> getNearbyEntities(final double v, final double v1, final double v2) {
return Collections.emptyList();
public void setHitbox(Hitbox hitbox) {
}
@Override
public Hitbox getHitbox() {
return null;
}
@Override
public void setStepHeight(double height) {
}
@Override
public Double getStepHeight() {
return null;
}
@Override
public void setCollidableToLiving(LivingEntity living, boolean isRemove) {
}
@Override
public void broadcastSpawnPacket() {
}
@Override
public void broadcastDespawnPacket() {
}
@Override
public int getEntityId() {
return -1;
}
@Override
public void remove() {
this.alive = false;
}
@Override
public boolean isCustomNameVisible() {
return false;
}
@Override
public boolean isDead() {
return !this.alive;
return this.entityId;
}
@Override
@@ -138,139 +177,66 @@ public class MEGEntity implements BaseEntity<MEGEntity> {
}
@Override
public EntityType getType() {
return EntityType.PUFFERFISH;
public Location getLocation() {
return location;
}
@Override
public boolean isInvulnerable() {
return true;
public World getWorld() {
return this.getWorld();
}
@Override
public boolean hasGravity() {
public boolean isDead() {
return alive;
}
@Override
public boolean isGlowing() {
return false;
}
@Override
public void setGravity(final boolean flag) {
public boolean isOnGround() {
return false;
}
@Override
public boolean isMoving() {
return false;
}
@Override
public void setYHeadRot(float rot) {
}
@Override
public double getHealth() {
return 1;
}
@Override
public double getMaxHealth() {
return 1;
}
@Override
public String getCustomName() {
return null;
}
@Override
public void setCustomName(final String s) {
}
@Override
public double getMovementSpeed() {
public float getYHeadRot() {
return 0;
}
@Override
public ItemStack getItemInMainHand() {
return null;
public float getXHeadRot() {
return 0;
}
@Override
public ItemStack getItemInOffHand() {
return null;
}
@Override
public boolean isLivingEntity() {
return false;
}
@Override
public void addPotionEffect(final PotionEffect potion) {
public void setYBodyRot(float rot) {
}
@Override
public void removePotionEffect(final PotionEffectType potion) {
public float getYBodyRot() {
return 0;
}
@Override
public void setEntitySize(final float width, final float height, final float eye) {
public List<Entity> getPassengers() {
return this.passengers;
}
@Override
public void sendDespawnPacket(final ModeledEntity modeledEntity) {
}
@Override
public void sendSpawnPacket(final ModeledEntity modeledEntity) {
}
@Override
public double getLastX() {
return this.location.getX();
}
@Override
public double getLastY() {
return this.location.getY();
}
@Override
public double getLastZ() {
return this.location.getZ();
}
@Override
public double getWantedX() {
return this.location.getX();
}
@Override
public double getWantedY() {
return this.location.getY();
}
@Override
public double getWantedZ() {
return this.location.getZ();
}
@Override
public void saveModelList(final Map<String, ActiveModel> models) {
}
@Override
public void saveModelInfo(final ModeledEntity model) {
}
@Override
public List<String> getModelList() {
return Collections.emptyList();
}
final EntityData entityData = new EntityData();
@Override
public EntityData loadModelInfo() {
return this.entityData;
public Vector getVelocity() {
return velocity;
}
}

View File

@@ -1,14 +1,18 @@
package io.github.fisher2911.hmccosmetics.listener;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.EquipmentSlot;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
public class ClickListener implements Listener {
@@ -56,15 +60,18 @@ public class ClickListener implements Listener {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
}
/*
// @EventHandler
// public void onArmorSlotClick(final InventoryClickEvent event) {
// final int slot = event.getSlot();
// if (!(event.getWhoClicked() instanceof final Player player)) return;
// if (slot >= 36 && slot <= 40) {
// this.fixInventory(player);
// }
// }
@EventHandler
public void onArmorSlotClick(final InventoryClickEvent event) {
final int slot = event.getSlot();
if (!(event.getWhoClicked() instanceof Player)) return;
if (slot >= 36 && slot <= 40) {
this.fixInventory(((Player) event.getWhoClicked()).getPlayer());
}
}
*/
//
// @EventHandler
// public void onBlockClick(final PlayerInteractEvent event) {
@@ -102,22 +109,25 @@ public class ClickListener implements Listener {
// this.userManager.get(player.getUniqueId()).ifPresent(this::doRunnable);
// }
//
// private void fixInventory(final Player player) {
// final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
//
// if (optionalUser.isEmpty()) {
// return;
// }
//
// this.doRunnable(optionalUser.get());
// }
//
// private void doRunnable(final User user) {
// Bukkit.getScheduler().runTaskLaterAsynchronously(
// this.plugin, () -> this.userManager.updateCosmetics(user),
// 1);
// }
//
/*
private void fixInventory(final Player player) {
final Optional<User> optionalUser = this.userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) {
return;
}
this.doRunnable(optionalUser.get());
}
private void doRunnable(final User user) {
Equipment equip = this.userManager.getItemList(user, user.getEquipment(), Collections.emptySet());
Bukkit.getScheduler().runTaskLaterAsynchronously(
this.plugin, () -> this.userManager.sendUpdatePacket(user, equip),
1);
}
*/
// private void checkFix(final Player player, final int clickedSlot, final ItemStack itemStack) {
// final EquipmentSlot slot = this.getArmorSlot(itemStack.getType());
// if (slot == null) return;
@@ -138,5 +148,4 @@ public class ClickListener implements Listener {
// }
// return null;
// }
}

View File

@@ -1,24 +1,23 @@
package io.github.fisher2911.hmccosmetics.listener;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientClickWindow;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerWindowItems;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayClientWindowClick;
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayServerWindowItems;
import io.github.fisher2911.hmccosmetics.task.DelayedTask;
import io.github.fisher2911.hmccosmetics.task.TaskManager;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -36,13 +35,8 @@ import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.logging.Level;
public class CosmeticFixListener implements Listener {
@@ -122,6 +116,7 @@ public class CosmeticFixListener implements Listener {
if (type == null) return;
this.taskManager.submit(() -> {
final EntityEquipment equipment = player.getEquipment();
final ItemStack current;
if (equipment == null) {
@@ -140,117 +135,139 @@ public class CosmeticFixListener implements Listener {
}
private void registerInventoryClickListener() {
PacketEvents.getAPI().getEventManager().registerListener(
new PacketListenerAbstract() {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() != PacketType.Play.Client.CLICK_WINDOW) return;
final WrapperPlayClientClickWindow packet = new WrapperPlayClientClickWindow(event);
if (packet.getWindowId() != 0) return;
if (!(event.getPlayer() instanceof final Player player)) return;
int slotClicked = packet.getSlot();
taskManager.submit(() -> {
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
EquipmentSlot slot = getPacketArmorSlot(slotClicked);
if (slot == null) {
return;
}
final EntityEquipment entityEquipment = player.getEquipment();
if (entityEquipment == null) return;
final ItemStack current = Utils.replaceIfNull(entityEquipment.getItem(slot), new ItemStack(Material.AIR));
final ArmorItem.Type type = ArmorItem.Type.fromEquipmentSlot(slot);
if (type == null) return;
updateOnClick(
player,
slot,
user,
type,
current
);
});
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmetics.getPlugin(HMCCosmetics.class), ListenerPriority.NORMAL, PacketType.Play.Client.WINDOW_CLICK) {
@Override
public void onPacketReceiving(PacketEvent event) {
Player player = event.getPlayer();
int invTypeClicked = event.getPacket().getIntegers().read(0);
int slotClicked = event.getPacket().getIntegers().read(2);
// Must be a player inventory.
if (invTypeClicked != 0) return;
// -999 is when a player clicks outside their inventory. https://wiki.vg/Inventory#Player_Inventory
if (slotClicked == -999) return;
if (!(event.getPlayer() instanceof Player)) return;
taskManager.submit(() -> {
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
EquipmentSlot slot = getPacketArmorSlot(slotClicked);
if (slot == null) {
return;
}
}
);
final EntityEquipment entityEquipment = player.getEquipment();
if (entityEquipment == null) return;
final ItemStack current = Utils.replaceIfNull(entityEquipment.getItem(slot), new ItemStack(Material.AIR));
final ArmorItem.Type type = ArmorItem.Type.fromEquipmentSlot(slot);
if (type == null) return;
updateOnClick(
player,
slot,
user,
type,
current
);
});
}
});
}
private void updateOnClick(final Player player, final EquipmentSlot slot, final User user, final ArmorItem.Type type, final ItemStack current) {
//plugin.getLogger().log(Level.INFO, "updateOnClick (171)");
final Location location = player.getLocation();
final Equipment equipment = Equipment.fromEntityEquipment(player.getEquipment());
final Equipment equipment = new Equipment();
final ItemStack cosmetic = userManager.getCosmeticItem(
user.getPlayerArmor().getItem(type),
current,
ArmorItem.Status.APPLIED,
slot
);
//plugin.getLogger().log(Level.INFO, "Set cosmetic in " + slot + " to " + cosmetic);
if (cosmetic != null && cosmetic.getType() != Material.AIR) equipment.setItem(slot, cosmetic);
//plugin.getLogger().log(Level.INFO, "Set cosmetic in " + slot + " to " + cosmetic + "(done)");
final List<com.github.retrooper.packetevents.protocol.player.Equipment> items =
userManager.getItemList(user, equipment, Collections.emptySet());
items.removeIf(e -> {
final com.github.retrooper.packetevents.protocol.player.EquipmentSlot s = e.getSlot();
final ArmorItem.Type t = ArmorItem.Type.fromPacketSlot(s);
if (t == null) return false;
/*
final Equipment items = userManager.getItemList(user, equipment, Collections.emptySet());
for (EquipmentSlot e : items.keys()) {
//final EquipmentSlot s = e.getSlot();
final ArmorItem.Type t = ArmorItem.Type.fromWrapper(e);
ItemStack air = new ItemStack(Material.AIR);
if (t == null) {
//plugin.getLogger().log(Level.INFO, "T is null");
equipment.setItem(e, air);
return;
}
final ArmorItem armorItem = user.getPlayerArmor().getItem(t);
final ItemStack i = SpigotConversionUtil.toBukkitItemStack(e.getItem());
return armorItem.isEmpty() && i.equals(equipment.getItem(t.getSlot()));
});
final ItemStack i = equipment.getItem(e);
if (i == null) {
//plugin.getLogger().log(Level.INFO, "I is null");
equipment.setItem(e, air);
return;
}
Boolean remove = armorItem.isEmpty() && i.equals(equipment.getItem(t.getSlot()));
if (remove) {
//plugin.getLogger().log(Level.INFO, "Boolean is true");
equipment.setItem(e, air);
return;
}
return;
}
*/
for (final Player other : Bukkit.getOnlinePlayers()) {
if (!settings.isInViewDistance(location, other.getLocation())) continue;
userManager.sendUpdatePacket(
user,
items
equipment
);
}
}
private void registerMenuChangeListener() {
PacketEvents.getAPI().getEventManager().registerListener(
new PacketListenerAbstract() {
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != PacketType.Play.Server.WINDOW_ITEMS) return;
final WrapperPlayServerWindowItems packet = new WrapperPlayServerWindowItems(event);
if (!(event.getPlayer() instanceof final Player player)) return;
final int windowId = packet.getWindowId();
final List<com.github.retrooper.packetevents.protocol.item.ItemStack> itemStacks = packet.getItems();
taskManager.submit(() -> {
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
if (windowId != 0) return;
final int size = itemStacks.size();
final PlayerArmor playerArmor = user.getPlayerArmor();
final List<com.github.retrooper.packetevents.protocol.player.Equipment> equipmentList = new ArrayList<>();
for (final ArmorItem armorItem : playerArmor.getArmorItems()) {
final ArmorItem.Type type = armorItem.getType();
final EquipmentSlot slot = type.getSlot();
if (slot == null) continue;
final int packetSlot = getPacketArmorSlot(slot);
if (packetSlot == -1) continue;
if (packetSlot >= size) continue;
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmetics.getPlugin(HMCCosmetics.class), ListenerPriority.NORMAL, PacketType.Play.Server.WINDOW_ITEMS) {
@Override
public void onPacketSending(PacketEvent event) {
Player player = event.getPlayer();
if (event.getPlayer() == null) return;
WrapperPlayServerWindowItems wrapper = new WrapperPlayServerWindowItems(event.getPacket());
if (!(event.getPlayer() instanceof Player)) return;
final int windowId = wrapper.getWindowId();
final ItemStack current = SpigotConversionUtil.toBukkitItemStack(itemStacks.get(packetSlot));
final com.github.retrooper.packetevents.protocol.item.ItemStack setTo =
SpigotConversionUtil.fromBukkitItemStack(userManager.getCosmeticItem(
armorItem,
current,
ArmorItem.Status.APPLIED,
slot
));
if (SpigotConversionUtil.fromBukkitItemStack(current).equals(setTo)) continue;
equipmentList.add(PacketManager.getEquipment(setTo, slot));
}
userManager.sendUpdatePacket(
user,
equipmentList
);
});
// packet.setItems(itemStacks);
List<ItemStack> items = wrapper.getSlotData();
taskManager.submit(() -> {
final Optional<User> optionalUser = userManager.get(player.getUniqueId());
if (optionalUser.isEmpty()) return;
final User user = optionalUser.get();
if (windowId != 0) return;
final int size = items.size();
final PlayerArmor playerArmor = user.getPlayerArmor();
final Equipment equip = userManager.getItemList(user);
for (final ArmorItem armorItem : playerArmor.getArmorItems()) {
final ArmorItem.Type type = armorItem.getType();
final EquipmentSlot slot = type.getSlot();
if (slot == null) continue;
final int packetSlot = getPacketArmorSlot(slot);
if (packetSlot == -1) continue;
if (packetSlot >= size) continue;
final ItemStack current = (items.get(packetSlot));
final ItemStack setTo =
(userManager.getCosmeticItem(
armorItem,
current,
ArmorItem.Status.APPLIED,
slot
));
if ((current).equals(setTo)) continue;
equip.setItem(slot, setTo);
}
}
);
userManager.sendUpdatePacket(
user,
equip
);
});
}
});
}
private int getPacketArmorSlot(final EquipmentSlot slot) {
@@ -349,10 +366,11 @@ public class CosmeticFixListener implements Listener {
}
return null;
}
/*
private void fixCosmetics(final Player player) {
Bukkit.getScheduler().runTaskLaterAsynchronously(this.plugin,
() -> this.userManager.updateCosmetics(player.getUniqueId()), 2);
}
*/
}

View File

@@ -1,5 +1,6 @@
package io.github.fisher2911.hmccosmetics.listener;
import com.comphenix.protocol.ProtocolLibrary;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.database.Database;
@@ -13,6 +14,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitScheduler;
import java.util.Optional;
@@ -36,16 +38,18 @@ public class JoinListener implements Listener {
user -> new TaskChain(this.plugin).chain(
() -> this.userManager.add(user)
).chain(() -> {
// this.userManager.resendCosmetics(player);
// this.userManager.updateCosmetics(user);
final WardrobeSettings settings = this.plugin.getSettings().getWardrobeSettings();
if (settings.isAlwaysDisplay() && settings.getWardrobeLocation() != null) {
final Wardrobe wardrobe = user.getWardrobe();
wardrobe.setCurrentLocation(settings.getWardrobeLocation());
wardrobe.spawnFakePlayer(player);
}
}, true).execute()
);
// and finally, resend the cosmetics
Bukkit.getScheduler().runTaskLaterAsynchronously(HMCCosmetics.getPlugin(HMCCosmetics.class),
() -> {
this.userManager.updateCosmetics(user);
}, 20);
}, true).execute());
}
@EventHandler

View File

@@ -1,9 +1,10 @@
package io.github.fisher2911.hmccosmetics.listener;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.user.UserManager;
import org.bukkit.Bukkit;
@@ -20,21 +21,21 @@ public class WardrobeListener implements Listener {
public WardrobeListener(final HMCCosmetics plugin) {
this.plugin = plugin;
this.userManager = this.plugin.getUserManager();
PacketEvents.getAPI().getEventManager().registerListener(
new PacketListenerAbstract() {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() != PacketType.Play.Client.ANIMATION) return;
if (!(event.getPlayer() instanceof final Player player)) return;
WardrobeListener.this.userManager.get(player.getUniqueId()).ifPresent(user -> {
if (!user.getWardrobe().isActive()) return;
Bukkit.getScheduler().runTask(plugin, () -> {
WardrobeListener.this.plugin.getCosmeticsMenu().openDefault(player);
});
}
);
}
});
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(HMCCosmetics.getPlugin(HMCCosmetics.class), ListenerPriority.NORMAL, PacketType.Play.Client.ARM_ANIMATION) {
@Override
public void onPacketReceiving(PacketEvent event) {
if (!(event.getPlayer() instanceof Player)) return;
Player player = event.getPlayer();
WardrobeListener.this.userManager.get(player.getUniqueId()).ifPresent(user -> {
if (!user.getWardrobe().isActive()) return;
Bukkit.getScheduler().runTask(plugin, () -> {
WardrobeListener.this.plugin.getCosmeticsMenu().openDefault(player);
});
}
);
}
});
}
@EventHandler

View File

@@ -1,128 +1,85 @@
package io.github.fisher2911.hmccosmetics.packet;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import com.github.retrooper.packetevents.protocol.player.GameMode;
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAttachEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRelativeMove;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRotation;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityVelocity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfo;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnLivingEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnPlayer;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import net.kyori.adventure.text.Component;
import io.github.fisher2911.hmccosmetics.packet.versions.PacketBase;
import io.github.fisher2911.hmccosmetics.packet.versions.PacketManager_1_19_2;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public class PacketManager {
//
// private static final PacketHelper PACKET_HELPER;
//
// static {
// final String version = Bukkit.getVersion();
// if (version.contains("1.16")) {
// PACKET_HELPER = new PacketHelper_1_16_R3();
// } else if (version.contains("1.17")) {
// PACKET_HELPER = new PacketHelper_1_17_R1();
// } else if (version.contains("1.18")) {
// PACKET_HELPER = new PacketHelper_1_18_R1();
// } else {
// PACKET_HELPER = null;
// }
// }
private static BiMap<List<String>, PacketBase> packetHelper = HashBiMap.create();
public static void sendArmorStandMetaContainer(final int armorStandId, final Collection<? extends Player> sendTo) {
sendArmorStandMetaContainer(armorStandId, sendTo.toArray(new Player[0]));
public static final PacketBase WildUpdate = new PacketManager_1_19_2();
private static PacketBase packetVersion;
public static void setupPackets() {
for (PacketBase packet : packetHelper.values()) {
for (String version : packet.getVersion()) {
if (Bukkit.getVersion().contains(version)) {
packetVersion = packet;
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().info("Found protocol support for your version. Choosing: " + packet.getVersion());
break;
}
}
}
if (packetVersion == null) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().severe("Unable to find proper support for your version. Defaulting packets to use 1.19.2 information. You can safely ignore this if you do not encounter any problems.");
packetVersion = WildUpdate;
}
}
public static void addPacketBase(PacketBase packet) {
if (packetHelper.containsKey(packet.getVersion())) {
HMCCosmetics.getPlugin(HMCCosmetics.class).getLogger().severe("A protocol version was duplicated! This has overriden the old packet support for that version. You can ignore if this is intentional.");
}
packetHelper.put(packet.getVersion(), packet);
}
/**
* Sends meta data for armor stands.
* @param armorStandId
* @param sendTo
*/
public static void sendArmorStandMetaContainer(final int armorStandId, final Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityMetadata(
armorStandId,
List.of(
new EntityData(0, EntityDataTypes.BYTE, (byte) 0x20),
new EntityData(15, EntityDataTypes.BYTE, (byte) 0x10)
)
));
}
packetVersion.sendArmorStandMetaContainer(armorStandId, sendTo);
}
/**
* Sends cloud meta data about an entity to a player (No idea what this means?)
* @param entityId
* @param sendTo
*/
public static void sendCloudMetaData(int entityId, Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityMetadata(
entityId,
List.of(
new EntityData(0, EntityDataTypes.BYTE, (byte) 0),
new EntityData(2, EntityDataTypes.OPTIONAL_COMPONENT, Optional.empty()),
new EntityData(6, EntityDataTypes.ENTITY_POSE, EntityPose.STANDING),
new EntityData(4, EntityDataTypes.BOOLEAN, false),
new EntityData(8, EntityDataTypes.FLOAT, 0.0f),
new EntityData(9, EntityDataTypes.INT, 0),
new EntityData(11, EntityDataTypes.PARTICLE, 21),
new EntityData(10, EntityDataTypes.BOOLEAN, false),
new EntityData(1, EntityDataTypes.INT, 300),
new EntityData(3, EntityDataTypes.BOOLEAN, false),
new EntityData(7, EntityDataTypes.INT, 0),
new EntityData(5, EntityDataTypes.BOOLEAN, false)
)
));
}
packetVersion.sendCloudMetaData(entityId, sendTo);
}
public static void sendVelocityPacket(final int entityId, Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityVelocity(
entityId,
new Vector3d(0.5, 0.5, 0.5)
));
}
}
/**
* Sends a movement packet relative to a position.
* @param entityId
* @param sendTo
*/
public static void sendRelativeMovePacket(final int entityId, Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityRelativeMove(
entityId,
0.0,
0.0,
0.0,
false
));
}
packetVersion.sendRelativeMovePacket(entityId, sendTo);
}
public static void sendHeadLookPacket(final int entityId, Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityHeadLook(
entityId,
0
));
}
public static void sendHeadLookPacket(int entityId, float yaw, Player... sendTo) {
packetVersion.sendHeadLookPacket(entityId, yaw, sendTo);
}
public static void sendEntitySpawnPacket(
@@ -130,7 +87,7 @@ public class PacketManager {
final int entityId,
final EntityType entityType,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, sendTo.toArray(new Player[0]));
packetVersion.sendEntitySpawnPacket(location, entityId, entityType, sendTo);
}
public static void sendEntitySpawnPacket(
@@ -138,7 +95,7 @@ public class PacketManager {
final int entityId,
final EntityType entityType,
final Player... sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, UUID.randomUUID(), sendTo);
packetVersion.sendEntitySpawnPacket(location, entityId, entityType, sendTo);
}
public static void sendEntitySpawnPacket(
@@ -147,30 +104,25 @@ public class PacketManager {
final EntityType entityType,
final UUID uuid,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, uuid, sendTo.toArray(new Player[0]));
packetVersion.sendEntitySpawnPacket(location, entityId, entityType, uuid, sendTo);
}
/**
* "Spawns" an entity for players. This entity is fake and is mearly client side.
* @param location Location to spawn the entity.
* @param entityId The entityID that is being spawned.
* @param entityType The entity type that is being spawned.
* @param uuid The UUID of the entity being spawned.
* @param sendTo Whom to send the packet to.
*/
public static void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerSpawnLivingEntity(
entityId,
uuid,
entityType,
new Vector3d(location.getX(), location.getY(), location.getZ()),
location.getYaw(),
location.getPitch(),
0f,
Vector3d.zero(),
Collections.emptyList()
));
}
packetVersion.sendEntitySpawnPacket(location, entityId, entityType, uuid, sendTo);
}
public static void sendEntityNotLivingSpawnPacket(
final Location location,
final int entityId,
@@ -178,32 +130,20 @@ public class PacketManager {
final UUID uuid,
int data,
final Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerSpawnEntity(
entityId,
Optional.of(uuid),
entityType,
new Vector3d(location.getX(), location.getY(), location.getZ()),
0,
0,
0f,
data,
Optional.of(Vector3d.zero())
));
}
packetVersion.sendEntityNotLivingSpawnPacket(location, entityId, entityType, uuid, data, sendTo);
}
public static void sendInvisibilityPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendInvisibilityPacket(entityId, sendTo.toArray(new Player[0]));
packetVersion.sendInvisibilityPacket(entityId, sendTo);
}
/**
* Will make a entity invisible
* @param entityId Which entity will this affect?
* @param sendTo Whom to send the packet to
*/
public static void sendInvisibilityPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityMetadata(
entityId,
List.of(new EntityData(0, EntityDataTypes.BYTE, (byte) 0x20))
));
}
packetVersion.sendInvisibilityPacket(entityId, sendTo);
}
public static void sendTeleportPacket(
@@ -212,24 +152,23 @@ public class PacketManager {
boolean onGround,
final Collection<? extends Player> sendTo
) {
sendTeleportPacket(entityId, location, onGround, sendTo.toArray(new Player[0]));
packetVersion.sendTeleportPacket(entityId, location, onGround, sendTo);
}
/**
* Used when a player is sent 8+ blocks.
* @param entityId Entity this affects
* @param location Location a player is being teleported to
* @param onGround If the packet is on the ground
* @param sendTo Whom to send the packet to
*/
public static void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityTeleport(
entityId,
new Vector3d(location.getX(), location.getY(), location.getZ()),
location.getYaw(),
location.getPitch(),
onGround
));
}
packetVersion.sendTeleportPacket(entityId, location, onGround, sendTo);
}
public static void sendMovePacket(
@@ -239,9 +178,17 @@ public class PacketManager {
final boolean onGround,
final Collection<? extends Player> sendTo
) {
sendMovePacket(entityId, from, to, onGround, sendTo.toArray(new Player[0]));
packetVersion.sendMovePacket(entityId, from, to, onGround, sendTo);
}
/**
* Sends a movement packet from one location to another
* @param entityId Entity this will affect
* @param from Previous location
* @param to New location
* @param onGround If the movement is on the ground
* @param sendTo Whom to send the packet to
*/
public static void sendMovePacket(
final int entityId,
final Location from,
@@ -249,15 +196,7 @@ public class PacketManager {
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityRelativeMove(
entityId,
to.getX() - from.getX(),
to.getY() - from.getY(),
to.getZ() - from.getZ(),
onGround
));
}
packetVersion.sendMovePacket(entityId, from, to, onGround, sendTo);
}
public static void sendLeashPacket(
@@ -265,67 +204,50 @@ public class PacketManager {
final int entityId,
final Collection<? extends Player> sendTo
) {
sendLeashPacket(balloonId, entityId, sendTo.toArray(new Player[0]));
packetVersion.sendLeashPacket(balloonId, entityId, sendTo);
}
/**
* Sends a leash packet, useful for balloons!
* @param leashedEntity Entity being leashed (ex. a horse)
* @param entityId Entity this is affecting (ex. a player)
* @param sendTo Whom to send the packet to
*/
public static void sendLeashPacket(
final int balloonId,
final int leashedEntity,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerAttachEntity(
balloonId,
entityId,
true
));
}
packetVersion.sendLeashPacket(leashedEntity, entityId, sendTo);
}
/**
* Useful for updating packet equipment on a player
* @param equipment The equipment that is being equiped for the player. THIS IS NOT REAL ARMOR, mearly packets. If a player attempts to remove their cosmetics, it will disappear.
* @param entityID Entity this will affect
* @param sendTo Whom to send the packet to
*/
public static void sendEquipmentPacket(
final List<Equipment> equipmentList,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendEquipmentPacket(equipmentList, entityId, sendTo.toArray(new Player[0]));
}
public static void sendEquipmentPacket(
final List<Equipment> equipmentList,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityEquipment(
entityId,
equipmentList
));
}
}
public static void sendRotationPacket(
final int entityId,
final Location location,
final boolean onGround,
final Collection<? extends Player> sendTo
) {
sendRotationPacket(entityId, location, onGround, sendTo.toArray(new Player[0]));
final Equipment equipment,
final int entityID,
final Player... sendTo) {
packetVersion.sendEquipmentPacket(equipment, entityID, sendTo);
}
/**
* Sends a rotation packet for an entity
* @param entityId EntityID that rotates their body
* @param location Location/Vector that will be looked at
* @param onGround Whether it is on the ground or not.
* @param sendTo Whom to send the packet to
*/
public static void sendRotationPacket(
final int entityId,
final Location location,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityRotation(
entityId,
location.getYaw(),
location.getPitch(),
onGround
));
}
packetVersion.sendRotationPacket(entityId, location, onGround, sendTo);
}
public static void sendLookPacket(
@@ -333,129 +255,104 @@ public class PacketManager {
final Location location,
final Collection<? extends Player> sendTo
) {
sendLookPacket(entityId, location, sendTo.toArray(new Player[0]));
packetVersion.sendLookPacket(entityId, location, sendTo);
}
/**
* Sends a look packet at a location
* @param entityId EntityID this packet affects
* @param location Location/Vector that an entity looks at.
* @param sendTo Whom to send the packet to
*/
public static void sendLookPacket(
final int entityId,
final Location location,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityHeadLook(
entityId,
location.getYaw()
));
}
}
public static void sendRidingPacket(
final int mountId,
final int passengerId,
final Collection<? extends Player> sendTo
) {
sendRidingPacket(mountId, passengerId, sendTo.toArray(new Player[0]));
packetVersion.sendLookPacket(entityId, location, sendTo);
}
/**
* Mostly to deal with backpacks, this deals with entities riding other entities.
* @param mountId The entity that is the "mount", ex. a player
* @param passengerId The entity that is riding the mount, ex. a armorstand for a backpack
* @param sendTo Whom to send the packet to
*/
public static void sendRidingPacket(
final int mountId,
final int passengerId,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerSetPassengers(
mountId,
new int[]{passengerId}
));
}
packetVersion.sendRidingPacket(mountId, passengerId, sendTo);
}
/**
* Destroys an entity from a player
* @param entityId The entity to delete for a player
* @param sendTo The players the packet should be sent to
*/
public static void sendEntityDestroyPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendEntityDestroyPacket(entityId, sendTo.toArray(new Player[0]));
packetVersion.sendEntityDestroyPacket(entityId, sendTo);
}
/**
* Destroys an entity from a player
* @param entityId The entity to delete for a player
* @param sendTo The players the packet should be sent to
*/
public static void sendEntityDestroyPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerDestroyEntities(entityId));
}
packetVersion.sendEntityDestroyPacket(entityId, sendTo);
}
/**
* Sends a camera packet
* @param entityId The Entity ID that camera will go towards
* @param sendTo The players that will be sent this packet
*/
public static void sendCameraPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerCamera(entityId));
}
packetVersion.sendCameraPacket(entityId, sendTo);
}
/**
* Sends a camera packet
* @param entity The Entity that camera will go towards
* @param sendTo The players that will be sent this packet
*/
public static void sendCameraPacket(final Entity entity, final Player... sendTo) {
packetVersion.sendCameraPacket(entity, sendTo);
}
/**
* Sends a camera packet
* @param entityId The Entity ID that camera will go towards
* @param sendTo The players that will be sent this packet
*/
public static void sendCameraPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendCameraPacket(entityId, sendTo.toArray(new Player[0]));
packetVersion.sendCameraPacket(entityId, sendTo);
}
// public static void sendSoundPacket(
// final Player player,
// final Location location,
// final MinecraftKey name,
// final float volume,
// final float pitch,
// final EnumWrappers.SoundCategory soundCategory,
// final Player...sendTo
// ) {
// final var packet = new WrapperPlayServerSoundEffect(
//
// );
// final var manager = ProtocolLibrary.getProtocolManager();
// final var packet = manager.createPacket(PacketType.Play.Server.CUSTOM_SOUND_EFFECT);
//
// packet.getMinecraftKeys()
// .write(
// 0,
// name
// );
//
// packet.getSoundCategories()
// .write(0, EnumWrappers.SoundCategory.valueOf(soundCategory.name()));
//
// packet.getIntegers()
// .write(0, location.getBlockX() * 8)
// .write(
// 1, location.getBlockY() * 8
// )
// .write(2, location.getBlockZ() * 8);
//
// packet.getFloat()
// .write(0, volume)
// .write(1, pitch);
//
// return packet;
// }
public static void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendFakePlayerSpawnPacket(location, uuid, entityId, sendTo.toArray(new Player[0]));
packetVersion.sendFakePlayerSpawnPacket(location, uuid, entityId, sendTo);
}
/**
*
* @param location Location of the fake player.
* @param uuid UUID of the fake player. Should be random.
* @param entityId The entityID that the entity will take on.
* @param sendTo Who should it send the packet to?
*/
public static void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerSpawnPlayer(
entityId,
uuid,
new com.github.retrooper.packetevents.protocol.world.Location(
location.getX(),
location.getY(),
location.getZ(),
location.getYaw(),
location.getPitch()
)
));
}
packetVersion.sendFakePlayerSpawnPacket(location, uuid, entityId, sendTo);
}
public static void sendFakePlayerInfoPacket(
@@ -463,54 +360,40 @@ public class PacketManager {
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendFakePlayerInfoPacket(skinnedPlayer, uuid, sendTo.toArray(new Player[0]));
packetVersion.sendFakePlayerInfoPacket(skinnedPlayer, uuid, sendTo);
}
/**
* Creates a fake player entity.
* @param skinnedPlayer The original player it bases itself off of.
* @param uuid UUID of the fake entity.
* @param sendTo Whom to send the packet to
*/
public static void sendFakePlayerInfoPacket(
final Player skinnedPlayer,
final UUID uuid,
final Player... sendTo
) {
final List<TextureProperty> textures = PacketEvents.getAPI().getPlayerManager().getUser(skinnedPlayer).getProfile().getTextureProperties();
final WrapperPlayServerPlayerInfo.PlayerData data = new WrapperPlayServerPlayerInfo.PlayerData(
Component.text(""),
new UserProfile(
uuid,
"",
textures
),
GameMode.CREATIVE,
0
);
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerPlayerInfo(
WrapperPlayServerPlayerInfo.Action.ADD_PLAYER,
data
));
}
packetVersion.sendFakePlayerInfoPacket(skinnedPlayer, uuid, sendTo);
}
public static void sendPlayerOverlayPacket(
final int playerId,
final Collection<? extends Player> sendTo
) {
sendPlayerOverlayPacket(playerId, sendTo.toArray(new Player[0]));
packetVersion.sendPlayerOverlayPacket(playerId, sendTo);
}
/**
* Generates the overlay packet for entities.
* @param playerId The entity the packet is about
* @param sendTo Whom is sent the packet.
*/
public static void sendPlayerOverlayPacket(
final int playerId,
final Player... sendTo
) {
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerEntityMetadata(
playerId,
List.of(
new EntityData(17, EntityDataTypes.BYTE, mask),
new EntityData(15, EntityDataTypes.BYTE, (byte) 0x10)
)
));
}
packetVersion.sendPlayerOverlayPacket(playerId, sendTo);
}
public static void sendRemovePlayerPacket(
@@ -518,69 +401,60 @@ public class PacketManager {
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendRemovePlayerPacket(player, uuid, sendTo.toArray(new Player[0]));
packetVersion.sendRemovePlayerPacket(player, uuid, sendTo);
}
/**
* Removes a fake player from being seen by players.
* @param player Which gameprofile to wrap for removing the player.
* @param uuid What is the fake player UUID
* @param sendTo Whom to send the packet to
*/
public static void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Player... sendTo
) {
for (final Player p : sendTo) {
sendPacketAsync(p, new WrapperPlayServerPlayerInfo(
WrapperPlayServerPlayerInfo.Action.REMOVE_PLAYER,
new WrapperPlayServerPlayerInfo.PlayerData(
Component.empty(),
new UserProfile(
uuid,
player.getDisplayName()
),
com.github.retrooper.packetevents.protocol.player.GameMode.SURVIVAL,
0
)
));
}
packetVersion.sendRemovePlayerPacket(player, uuid, sendTo);
}
public static void sendPacketAsync(final Player player, final PacketWrapper<?> packet) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmetics.getPlugin(HMCCosmetics.class), () ->
PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet)
);
/**
* Sends a gamemode change packet to a player.
* @param player Player to change their gamemode.
* @param gamemode Bukkit gamemode to change it to
*/
public static void sendGameModeChange(
final Player player,
final GameMode gamemode
) {
packetVersion.sendGameModeChange(player, gamemode);
}
public static void sendPacketAsyncSilently(final Player player, final PacketWrapper<?> packet) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmetics.getPlugin(HMCCosmetics.class), () ->
PacketEvents.getAPI().getPlayerManager().sendPacketSilently(player, packet)
);
}
public static com.github.retrooper.packetevents.protocol.player.Equipment getEquipment(
final ItemStack itemStack,
final org.bukkit.inventory.EquipmentSlot slot
/**
* Sends a gamemode change packet to a player.
* @param player Player to change their gamemode.
* @param gamemode Gamemode value to change it to
*/
public static void sendGameModeChange(
final Player player,
final int gamemode
) {
return getEquipment(SpigotConversionUtil.fromBukkitItemStack(itemStack), slot);
packetVersion.sendGameModeChange(player, gamemode);
}
public static com.github.retrooper.packetevents.protocol.player.Equipment getEquipment(
final com.github.retrooper.packetevents.protocol.item.ItemStack itemStack,
final org.bukkit.inventory.EquipmentSlot slot
) {
return new com.github.retrooper.packetevents.protocol.player.Equipment(
PacketManager.fromBukkitSlot(slot),
itemStack
);
public static void sendNewTeam(
final Player skinnedPlayer,
final Player... sendTo) {
packetVersion.sendNewTeam(skinnedPlayer, sendTo);
}
public static EquipmentSlot fromBukkitSlot(final org.bukkit.inventory.EquipmentSlot slot) {
return switch (slot) {
case HEAD -> EquipmentSlot.HELMET;
case CHEST -> EquipmentSlot.CHEST_PLATE;
case LEGS -> EquipmentSlot.LEGGINGS;
case FEET -> EquipmentSlot.BOOTS;
case HAND -> EquipmentSlot.MAIN_HAND;
case OFF_HAND -> EquipmentSlot.OFF_HAND;
};
/**
* This sends a packet to a player asyncronously, preventing clogging on the main thread.
* @param player Which player to send the packet to
* @param packet What packet to send to the player
*/
public static void sendPacketAsync(final Player player, final PacketContainer packet) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmetics.getPlugin(HMCCosmetics.class),
() -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet));
}
}

View File

@@ -1,37 +0,0 @@
package io.github.fisher2911.hmccosmetics.packet;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
public class WrapperPlayServerCamera extends PacketWrapper<WrapperPlayServerCamera> {
private int entityID;
public WrapperPlayServerCamera(final int entityID) {
super(PacketType.Play.Server.CAMERA);
this.entityID = entityID;
}
@Override
public void read() {
this.entityID = this.readVarInt();
}
@Override
public void copy(WrapperPlayServerCamera wrapper) {
this.entityID = wrapper.entityID;
}
public void write() {
this.writeVarInt(this.entityID);
}
public int getEntityId() {
return this.entityID;
}
public void setEntityIds(int entityID) {
this.entityID = entityID;
}
}

View File

@@ -0,0 +1,514 @@
package io.github.fisher2911.hmccosmetics.packet.versions;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.*;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayServerNamedEntitySpawn;
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayServerPlayerInfo;
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayServerRelEntityMove;
import io.github.fisher2911.hmccosmetics.packet.wrappers.WrapperPlayServerRelEntityMoveLook;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.util.PlayerUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
public class PacketBase {
// This is a PacketBase made to be in parity with the latest version. Other classes can override certain methods.
List<String> version;
protected PacketBase(@NotNull final List<String> version) {
this.version = version;
PacketManager.addPacketBase(this);
}
public List<String> getVersion() {
return version;
}
public void sendArmorStandMetaContainer(final int armorStandId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, armorStandId);
WrappedDataWatcher metadata = new WrappedDataWatcher();
//final WrappedDataWatcher.Serializer serializer = WrappedDataWatcher.Registry.get(Byte.class);
if (metadata == null) return;
// 0x10 & 0x20
metadata.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20);
metadata.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x10);
packet.getWatchableCollectionModifier().write(0, metadata.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
public void sendCloudMetaData(int entityId, Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, entityId);
WrappedDataWatcher wrapper = new WrappedDataWatcher();
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20);
//wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.get(Optional.class)), Optional.empty());
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(6, WrappedDataWatcher.Registry.get(EnumWrappers.EntityPose.class)), EnumWrappers.EntityPose.STANDING);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(4, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(8, WrappedDataWatcher.Registry.get(Float.class)), 0.0f);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(9, WrappedDataWatcher.Registry.get(int.class)), 0);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(11, WrappedDataWatcher.Registry.get(EnumWrappers.Particle.class)), 21);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(10, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(4, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(5, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(1, WrappedDataWatcher.Registry.get(int.class)), 300);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(7, WrappedDataWatcher.Registry.get(int.class)), 0);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
public void sendRelativeMovePacket(final int entityId, Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet);
wrapper.setDx(0.0);
wrapper.setDy(0.0);
wrapper.setDz(0.0);
wrapper.setOnGround(false);
sendPacketAsync(p, wrapper.getHandle());
}
}
public void sendHeadLookPacket(int entityId, float yaw, Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE_LOOK);
WrapperPlayServerRelEntityMoveLook wrapper = new WrapperPlayServerRelEntityMoveLook(packet);
wrapper.setYaw(yaw);
wrapper.setEntityID(entityId);
sendPacketAsync(p, wrapper.getHandle());
}
}
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, sendTo.toArray(new Player[0]));
}
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final Player... sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, UUID.randomUUID(), sendTo);
}
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, uuid, sendTo.toArray(new Player[0]));
}
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
packet.getModifier().writeDefaults();
packet.getUUIDs().write(0, uuid);
packet.getIntegers().write(0, entityId);
packet.getEntityTypeModifier().write(0, entityType);
packet.getDoubles().
write(0, location.getX()).
write(1, location.getY()).
write(2, location.getZ());
sendPacketAsync(p, packet);
}
}
@Deprecated
public void sendEntityNotLivingSpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
int data,
final Player... sendTo) {
for (final Player p : sendTo) {
}
}
public void sendInvisibilityPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendInvisibilityPacket(entityId, sendTo.toArray(new Player[0]));
}
public void sendInvisibilityPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, entityId);
WrappedDataWatcher wrapper = new WrappedDataWatcher();
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
public void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Collection<? extends Player> sendTo
) {
sendTeleportPacket(entityId, location, onGround, sendTo.toArray(new Player[0]));
}
public void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
packet.getIntegers().write(0, entityId);
packet.getDoubles().write(0, location.getX());
packet.getDoubles().write(1, location.getY());
packet.getDoubles().write(2, location.getZ());
packet.getBytes().write(0, (byte) (location.getYaw() * 256.0F / 360.0F));
packet.getBytes().write(1, (byte) (location.getPitch() * 256.0F / 360.0F));
packet.getBooleans().write(0, onGround);
sendPacketAsync(p, packet);
}
}
public void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final boolean onGround,
final Collection<? extends Player> sendTo
) {
sendMovePacket(entityId, from, to, onGround, sendTo.toArray(new Player[0]));
}
public void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet);
wrapper.setEntityID(entityId);
wrapper.setDx(to.getX() - from.getX());
wrapper.setDy(to.getY() - from.getY());
wrapper.setDz(to.getZ() - from.getZ());
wrapper.setOnGround(onGround);
sendPacketAsync(p, wrapper.getHandle());
}
}
public void sendLeashPacket(
final int balloonId,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendLeashPacket(balloonId, entityId, sendTo.toArray(new Player[0]));
}
public void sendLeashPacket(
final int leashedEntity,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY);
packet.getIntegers().write(0, leashedEntity);
packet.getIntegers().write(1, entityId);
// Leash?
//packet.getBooleans().write(0, true);
/*
sendPacketAsync(p, new WrapperPlayServerAttachEntity(
balloonId,
entityId,
true
));
*/
sendPacketAsync(p, packet);
}
}
public void sendEquipmentPacket(
final Equipment equipment,
final int entityID,
final Player... sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
packet.getIntegers().write(0, entityID);
List<Pair<EnumWrappers.ItemSlot, ItemStack>> list = new ArrayList<>();
for (EquipmentSlot slot : equipment.keys()) {
if (PlayerUtils.itemBukkitSlot(slot) != null) list.add(new Pair<>(PlayerUtils.itemBukkitSlot(slot), equipment.getItem(slot)));
}
if (list == null) return;
packet.getSlotStackPairLists().write(0, list);
for (Player p : sendTo) {
sendPacketAsync(p, packet);
}
}
public void sendRotationPacket(
final int entityId,
final Location location,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_LOOK);
packet.getIntegers().write(0, entityId);
float ROTATION_FACTOR = 256.0F / 360.0F;
packet.getBytes().write(0, (byte) (location.getYaw() * ROTATION_FACTOR));
packet.getBytes().write(1, (byte) (location.getPitch() * ROTATION_FACTOR));
//Bukkit.getLogger().info("DEBUG: Yaw: " + (location.getYaw() * ROTATION_FACTOR) + " | Original Yaw: " + location.getYaw());
packet.getBooleans().write(0, onGround);
sendPacketAsync(p, packet);
}
}
public void sendLookPacket(
final int entityId,
final Location location,
final Collection<? extends Player> sendTo
) {
sendLookPacket(entityId, location, sendTo.toArray(new Player[0]));
}
public void sendLookPacket(
final int entityId,
final Location location,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION);
packet.getIntegers().write(0, entityId);
packet.getBytes().write(0, (byte) (location.getYaw() * 256.0F / 360.0F));
sendPacketAsync(p, packet);
}
}
public void sendRidingPacket(
final int mountId,
final int passengerId,
final Player... sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT);
packet.getIntegers().write(0, mountId);
packet.getIntegerArrays().write(0, new int[]{passengerId});
for (final Player p : sendTo) {
//p.sendMessage("MountID: " + mountId + " / Raw Passenger: " + passengerId + " | Next Entity: " + Database.getNextEntityId());
sendPacketAsync(p, packet);
}
}
public void sendEntityDestroyPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendEntityDestroyPacket(entityId, sendTo.toArray(new Player[0]));
}
public void sendEntityDestroyPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
packet.getModifier().write(0, new IntArrayList(new int[]{entityId}));
sendPacketAsync(p, packet);
}
}
public void sendCameraPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.CAMERA);
packet.getIntegers().write(0, entityId);
sendPacketAsync(p, packet);
}
}
public void sendCameraPacket(final Entity entity, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.CAMERA);
packet.getEntityModifier(p.getWorld()).write(0, entity);
sendPacketAsync(p, packet);
}
}
public void sendCameraPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendCameraPacket(entityId, sendTo.toArray(new Player[0]));
}
public void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendFakePlayerSpawnPacket(location, uuid, entityId, sendTo.toArray(new Player[0]));
}
public void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
WrapperPlayServerNamedEntitySpawn wrapper = new WrapperPlayServerNamedEntitySpawn();
wrapper.setEntityID(entityId);
wrapper.setPlayerUUID(uuid);
wrapper.setPosition(location.toVector());
wrapper.setPitch(location.getPitch());
wrapper.setYaw(location.getYaw());
sendPacketAsync(p, wrapper.getHandle());
}
}
public void sendFakePlayerInfoPacket(
final Player skinnedPlayer,
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendFakePlayerInfoPacket(skinnedPlayer, uuid, sendTo.toArray(new Player[0]));
}
public void sendFakePlayerInfoPacket(
final Player skinnedPlayer,
final UUID uuid,
final Player... sendTo
) {
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo();
info.setAction(EnumWrappers.PlayerInfoAction.ADD_PLAYER);
String name = "Mannequin-" + skinnedPlayer.getEntityId();
while (name.length() > 16) {
name = name.substring(16);
}
WrappedGameProfile wrappedGameProfile = new WrappedGameProfile(uuid, name);
wrappedGameProfile.getProperties().put("textures", PlayerUtils.getSkin(skinnedPlayer));
info.setData(List.of(new PlayerInfoData(wrappedGameProfile, 0, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(name))));
for (final Player p : sendTo) {
sendPacketAsync(p, info.getHandle());
}
}
public void sendPlayerOverlayPacket(
final int playerId,
final Collection<? extends Player> sendTo
) {
sendPlayerOverlayPacket(playerId, sendTo.toArray(new Player[0]));
}
public void sendPlayerOverlayPacket(
final int playerId,
final Player... sendTo
) {
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, playerId);
WrappedDataWatcher wrapper = new WrappedDataWatcher();
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(17, WrappedDataWatcher.Registry.get(Byte.class)), mask);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x10);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
public void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendRemovePlayerPacket(player, uuid, sendTo.toArray(new Player[0]));
}
public void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Player... sendTo
) {
for (final Player p : sendTo) {
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo();
info.setAction(EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
String name = "Mannequin-" + player.getEntityId();
while (name.length() > 16) {
name = name.substring(16);
}
info.setData(List.of(new PlayerInfoData(new WrappedGameProfile(uuid, player.getName()), 0, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(name))));
sendPacketAsync(p, info.getHandle());
}
}
public void sendGameModeChange(
final Player player,
final GameMode gamemode
) {
sendGameModeChange(player, PlayerUtils.convertGamemode(gamemode));
}
public void sendGameModeChange(
final Player player,
final int gamemode
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.GAME_STATE_CHANGE);
packet.getGameStateIDs().write(0, 3);
// Tells what event this is. This is a change gamemode event.
packet.getFloat().write(0, (float) gamemode);
sendPacketAsync(player, packet);
}
public void sendNewTeam(
final Player skinnedPlayer,
final Player... sendTo)
{
PacketContainer packet = new PacketContainer(PacketType.Play.Server.SCOREBOARD_TEAM);
packet.getStrings().write(0, "npcteam");
packet.getBytes().write(0, (byte) 0);
packet.getStrings().write(1, " "); // Team Displayname?
packet.getStrings().write(2, "always");
String name = "Mannequin-" + skinnedPlayer.getEntityId();
while (name.length() > 16) {
name = name.substring(16);
}
String[] nameList = new String[]{name};
packet.getStringArrays().write(0, nameList);
for (Player player : sendTo) {
sendPacketAsync(player, packet);
}
}
public void sendPacketAsync(final Player player, final PacketContainer packet) {
Bukkit.getScheduler().runTaskAsynchronously(HMCCosmetics.getPlugin(HMCCosmetics.class),
() -> ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet));
}
}

View File

@@ -0,0 +1,654 @@
package io.github.fisher2911.hmccosmetics.packet.versions;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.*;
import io.github.fisher2911.hmccosmetics.packet.wrappers.*;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import io.github.fisher2911.hmccosmetics.util.PlayerUtils;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
public class PacketManager_1_19_2 extends PacketBase {
public PacketManager_1_19_2() {
super(List.of("1.19", "1.19.1", "1.19.2"));
}
/**
* Sends meta data for armor stands.
* @param armorStandId
* @param sendTo
*/
@Override
public void sendArmorStandMetaContainer(final int armorStandId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, armorStandId);
WrappedDataWatcher metadata = new WrappedDataWatcher();
if (metadata == null) return;
// 0x10 & 0x20
metadata.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20);
metadata.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x10);
packet.getWatchableCollectionModifier().write(0, metadata.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
/**
* Sends cloud meta data about an entity to a player (No idea what this means?)
* @param entityId
* @param sendTo
*/
@Override
public void sendCloudMetaData(int entityId, Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, entityId);
WrappedDataWatcher wrapper = new WrappedDataWatcher();
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20);
//wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.get(Optional.class)), Optional.empty());
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(6, WrappedDataWatcher.Registry.get(EnumWrappers.EntityPose.class)), EnumWrappers.EntityPose.STANDING);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(4, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(8, WrappedDataWatcher.Registry.get(Float.class)), 0.0f);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(9, WrappedDataWatcher.Registry.get(int.class)), 0);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(11, WrappedDataWatcher.Registry.get(EnumWrappers.Particle.class)), 21);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(10, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(4, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(5, WrappedDataWatcher.Registry.get(Boolean.class)), false);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(1, WrappedDataWatcher.Registry.get(int.class)), 300);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(7, WrappedDataWatcher.Registry.get(int.class)), 0);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
/**
* Sends a movement packet relative to a position.
* @param entityId
* @param sendTo
*/
@Override
public void sendRelativeMovePacket(final int entityId, Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet);
wrapper.setDx(0.0);
wrapper.setDy(0.0);
wrapper.setDz(0.0);
wrapper.setOnGround(false);
sendPacketAsync(p, wrapper.getHandle());
}
}
@Override
public void sendHeadLookPacket(int entityId, float yaw, Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE_LOOK);
WrapperPlayServerRelEntityMoveLook wrapper = new WrapperPlayServerRelEntityMoveLook(packet);
wrapper.setYaw(yaw);
wrapper.setEntityID(entityId);
sendPacketAsync(p, wrapper.getHandle());
}
}
@Override
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, sendTo.toArray(new Player[0]));
}
@Override
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final Player... sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, UUID.randomUUID(), sendTo);
}
@Override
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Collection<? extends Player> sendTo) {
sendEntitySpawnPacket(location, entityId, entityType, uuid, sendTo.toArray(new Player[0]));
}
/**
* "Spawns" an entity for players. This entity is fake and is mearly client side.
* @param location Location to spawn the entity.
* @param entityId The entityID that is being spawned.
* @param entityType The entity type that is being spawned.
* @param uuid The UUID of the entity being spawned.
* @param sendTo Whom to send the packet to.
*/
@Override
public void sendEntitySpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
packet.getModifier().writeDefaults();
packet.getUUIDs().write(0, uuid);
packet.getIntegers().write(0, entityId);
packet.getEntityTypeModifier().write(0, entityType);
packet.getDoubles().
write(0, location.getX()).
write(1, location.getY()).
write(2, location.getZ());
sendPacketAsync(p, packet);
}
}
@Deprecated @Override
public void sendEntityNotLivingSpawnPacket(
final Location location,
final int entityId,
final EntityType entityType,
final UUID uuid,
int data,
final Player... sendTo) {
for (final Player p : sendTo) {
}
}
@Override
public void sendInvisibilityPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendInvisibilityPacket(entityId, sendTo.toArray(new Player[0]));
}
/**
* Will make a entity invisible
* @param entityId Which entity will this affect?
* @param sendTo Whom to send the packet to
*/
@Override
public void sendInvisibilityPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, entityId);
WrappedDataWatcher wrapper = new WrappedDataWatcher();
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x20);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
@Override
public void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Collection<? extends Player> sendTo
) {
sendTeleportPacket(entityId, location, onGround, sendTo.toArray(new Player[0]));
}
/**
* Used when a player is sent 8+ blocks.
* @param entityId Entity this affects
* @param location Location a player is being teleported to
* @param onGround If the packet is on the ground
* @param sendTo Whom to send the packet to
*/
@Override
public void sendTeleportPacket(
final int entityId,
final Location location,
boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
packet.getIntegers().write(0, entityId);
packet.getDoubles().write(0, location.getX());
packet.getDoubles().write(1, location.getY());
packet.getDoubles().write(2, location.getZ());
packet.getBytes().write(0, (byte) (location.getYaw() * 256.0F / 360.0F));
packet.getBytes().write(1, (byte) (location.getPitch() * 256.0F / 360.0F));
packet.getBooleans().write(0, onGround);
sendPacketAsync(p, packet);
}
}
@Override
public void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final boolean onGround,
final Collection<? extends Player> sendTo
) {
sendMovePacket(entityId, from, to, onGround, sendTo.toArray(new Player[0]));
}
/**
* Sends a movement packet from one location to another
* @param entityId Entity this will affect
* @param from Previous location
* @param to New location
* @param onGround If the movement is on the ground
* @param sendTo Whom to send the packet to
*/
@Override
public void sendMovePacket(
final int entityId,
final Location from,
final Location to,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.REL_ENTITY_MOVE);
WrapperPlayServerRelEntityMove wrapper = new WrapperPlayServerRelEntityMove(packet);
wrapper.setEntityID(entityId);
wrapper.setDx(to.getX() - from.getX());
wrapper.setDy(to.getY() - from.getY());
wrapper.setDz(to.getZ() - from.getZ());
wrapper.setOnGround(onGround);
sendPacketAsync(p, wrapper.getHandle());
}
}
@Override
public void sendLeashPacket(
final int balloonId,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendLeashPacket(balloonId, entityId, sendTo.toArray(new Player[0]));
}
/**
* Sends a leash packet, useful for balloons!
* @param leashedEntity Entity being leashed (ex. a horse)
* @param entityId Entity this is affecting (ex. a player)
* @param sendTo Whom to send the packet to
*/
@Override
public void sendLeashPacket(
final int leashedEntity,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY);
packet.getIntegers().write(0, leashedEntity);
packet.getIntegers().write(1, entityId);
// Leash?
//packet.getBooleans().write(0, true);
/*
sendPacketAsync(p, new WrapperPlayServerAttachEntity(
balloonId,
entityId,
true
));
*/
sendPacketAsync(p, packet);
}
}
/**
* Useful for updating packet equipment on a player
* @param equipment The equipment that is being equiped for the player. THIS IS NOT REAL ARMOR, mearly packets. If a player attempts to remove their cosmetics, it will disappear.
* @param entityID Entity this will affect
* @param sendTo Whom to send the packet to
*/
@Override
public void sendEquipmentPacket(
final Equipment equipment,
final int entityID,
final Player... sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_EQUIPMENT);
packet.getIntegers().write(0, entityID);
List<Pair<EnumWrappers.ItemSlot, ItemStack>> list = new ArrayList<>();
for (EquipmentSlot slot : equipment.keys()) {
if (PlayerUtils.itemBukkitSlot(slot) != null) list.add(new Pair<>(PlayerUtils.itemBukkitSlot(slot), equipment.getItem(slot)));
}
if (list.isEmpty() || list == null) return;
packet.getSlotStackPairLists().write(0, list);
for (Player p : sendTo) {
sendPacketAsync(p, packet);
}
}
/**
* Sends a rotation packet for an entity
* @param entityId EntityID that rotates their body
* @param location Location/Vector that will be looked at
* @param onGround Whether it is on the ground or not.
* @param sendTo Whom to send the packet to
*/
@Override
public void sendRotationPacket(
final int entityId,
final Location location,
final boolean onGround,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_LOOK);
packet.getIntegers().write(0, entityId);
float ROTATION_FACTOR = 256.0F / 360.0F;
packet.getBytes().write(0, (byte) (location.getYaw() * ROTATION_FACTOR));
packet.getBytes().write(1, (byte) (location.getPitch() * ROTATION_FACTOR));
//Bukkit.getLogger().info("DEBUG: Yaw: " + (location.getYaw() * ROTATION_FACTOR) + " | Original Yaw: " + location.getYaw());
packet.getBooleans().write(0, onGround);
sendPacketAsync(p, packet);
}
}
@Override
public void sendLookPacket(
final int entityId,
final Location location,
final Collection<? extends Player> sendTo
) {
sendLookPacket(entityId, location, sendTo.toArray(new Player[0]));
}
/**
* Sends a look packet at a location
* @param entityId EntityID this packet affects
* @param location Location/Vector that an entity looks at.
* @param sendTo Whom to send the packet to
*/
@Override
public void sendLookPacket(
final int entityId,
final Location location,
final Player... sendTo
) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_HEAD_ROTATION);
packet.getIntegers().write(0, entityId);
packet.getBytes().write(0, (byte) (location.getYaw() * 256.0F / 360.0F));
sendPacketAsync(p, packet);
}
}
/**
* Mostly to deal with backpacks, this deals with entities riding other entities.
* @param mountId The entity that is the "mount", ex. a player
* @param passengerId The entity that is riding the mount, ex. a armorstand for a backpack
* @param sendTo Whom to send the packet to
*/
@Override
public void sendRidingPacket(
final int mountId,
final int passengerId,
final Player... sendTo
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.MOUNT);
packet.getIntegers().write(0, mountId);
packet.getIntegerArrays().write(0, new int[]{passengerId});
for (final Player p : sendTo) {
//p.sendMessage("MountID: " + mountId + " / Raw Passenger: " + passengerId + " | Next Entity: " + Database.getNextEntityId());
sendPacketAsync(p, packet);
}
}
/**
* Destroys an entity from a player
* @param entityId The entity to delete for a player
* @param sendTo The players the packet should be sent to
*/
@Override
public void sendEntityDestroyPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendEntityDestroyPacket(entityId, sendTo.toArray(new Player[0]));
}
/**
* Destroys an entity from a player
* @param entityId The entity to delete for a player
* @param sendTo The players the packet should be sent to
*/
@Override
public void sendEntityDestroyPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
packet.getModifier().write(0, new IntArrayList(new int[]{entityId}));
sendPacketAsync(p, packet);
}
}
/**
* Sends a camera packet
* @param entityId The Entity ID that camera will go towards
* @param sendTo The players that will be sent this packet
*/
@Override
public void sendCameraPacket(final int entityId, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.CAMERA);
packet.getIntegers().write(0, entityId);
sendPacketAsync(p, packet);
}
}
/**
* Sends a camera packet
* @param entity The Entity that camera will go towards
* @param sendTo The players that will be sent this packet
*/
@Override
public void sendCameraPacket(final Entity entity, final Player... sendTo) {
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.CAMERA);
packet.getEntityModifier(p.getWorld()).write(0, entity);
sendPacketAsync(p, packet);
}
}
/**
* Sends a camera packet
* @param entityId The Entity ID that camera will go towards
* @param sendTo The players that will be sent this packet
*/
@Override
public void sendCameraPacket(final int entityId, final Collection<? extends Player> sendTo) {
sendCameraPacket(entityId, sendTo.toArray(new Player[0]));
}
@Override
public void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Collection<? extends Player> sendTo
) {
sendFakePlayerSpawnPacket(location, uuid, entityId, sendTo.toArray(new Player[0]));
}
/**
*
* @param location Location of the fake player.
* @param uuid UUID of the fake player. Should be random.
* @param entityId The entityID that the entity will take on.
* @param sendTo Who should it send the packet to?
*/
@Override
public void sendFakePlayerSpawnPacket(
final Location location,
final UUID uuid,
final int entityId,
final Player... sendTo
) {
for (final Player p : sendTo) {
WrapperPlayServerNamedEntitySpawn wrapper = new WrapperPlayServerNamedEntitySpawn();
wrapper.setEntityID(entityId);
wrapper.setPlayerUUID(uuid);
wrapper.setPosition(location.toVector());
wrapper.setPitch(location.getPitch());
wrapper.setYaw(location.getYaw());
sendPacketAsync(p, wrapper.getHandle());
}
}
@Override
public void sendFakePlayerInfoPacket(
final Player skinnedPlayer,
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendFakePlayerInfoPacket(skinnedPlayer, uuid, sendTo.toArray(new Player[0]));
}
/**
* Creates a fake player entity.
* @param skinnedPlayer The original player it bases itself off of.
* @param uuid UUID of the fake entity.
* @param sendTo Whom to send the packet to
*/
@Override
public void sendFakePlayerInfoPacket(
final Player skinnedPlayer,
final UUID uuid,
final Player... sendTo
) {
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo();
info.setAction(EnumWrappers.PlayerInfoAction.ADD_PLAYER);
String name = "Mannequin-" + skinnedPlayer.getEntityId();
while (name.length() > 16) {
name = name.substring(16);
}
WrappedGameProfile wrappedGameProfile = new WrappedGameProfile(uuid, name);
wrappedGameProfile.getProperties().put("textures", PlayerUtils.getSkin(skinnedPlayer));
info.setData(List.of(new PlayerInfoData(wrappedGameProfile, 0, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(name))));
for (final Player p : sendTo) {
sendPacketAsync(p, info.getHandle());
}
}
@Override
public void sendPlayerOverlayPacket(
final int playerId,
final Collection<? extends Player> sendTo
) {
sendPlayerOverlayPacket(playerId, sendTo.toArray(new Player[0]));
}
/**
* Generates the overlay packet for entities.
* @param playerId The entity the packet is about
* @param sendTo Whom is sent the packet.
*/
@Override
public void sendPlayerOverlayPacket(
final int playerId,
final Player... sendTo
) {
/*
0x01 = Is on fire
0x02 = Is courching
0x04 = Unusued
0x08 = Sprinting
0x10 = Is swimming
0x20 = Invisibile
0x40 = Is Glowing
0x80 = Is flying with an elytra
https://wiki.vg/Entity_metadata#Entity
*/
final byte mask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x40;
for (final Player p : sendTo) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getModifier().writeDefaults();
packet.getIntegers().write(0, playerId);
WrappedDataWatcher wrapper = new WrappedDataWatcher();
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(17, WrappedDataWatcher.Registry.get(Byte.class)), mask);
wrapper.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(15, WrappedDataWatcher.Registry.get(Byte.class)), (byte) 0x10);
packet.getWatchableCollectionModifier().write(0, wrapper.getWatchableObjects());
sendPacketAsync(p, packet);
}
}
@Override
public void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Collection<? extends Player> sendTo
) {
sendRemovePlayerPacket(player, uuid, sendTo.toArray(new Player[0]));
}
/**
* Removes a fake player from being seen by players.
* @param player Which gameprofile to wrap for removing the player.
* @param uuid What is the fake player UUID
* @param sendTo Whom to send the packet to
*/
@Override
public void sendRemovePlayerPacket(
final Player player,
final UUID uuid,
final Player... sendTo
) {
for (final Player p : sendTo) {
WrapperPlayServerPlayerInfo info = new WrapperPlayServerPlayerInfo();
info.setAction(EnumWrappers.PlayerInfoAction.REMOVE_PLAYER);
String name = "Mannequin-" + player.getEntityId();
while (name.length() > 16) {
name = name.substring(16);
}
info.setData(List.of(new PlayerInfoData(new WrappedGameProfile(uuid, player.getName()), 0, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(name))));
sendPacketAsync(p, info.getHandle());
}
}
/**
* Sends a gamemode change packet to a player.
* @param player Player to change their gamemode.
* @param gamemode Bukkit gamemode to change it to
*/
@Override
public void sendGameModeChange(
final Player player,
final GameMode gamemode
) {
sendGameModeChange(player, PlayerUtils.convertGamemode(gamemode));
}
/**
* Sends a gamemode change packet to a player.
* @param player Player to change their gamemode.
* @param gamemode Gamemode value to change it to
*/
@Override
public void sendGameModeChange(
final Player player,
final int gamemode
) {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.GAME_STATE_CHANGE);
packet.getGameStateIDs().write(0, 3);
// Tells what event this is. This is a change gamemode event.
packet.getFloat().write(0, (float) gamemode);
sendPacketAsync(player, packet);
}
@Override
public void sendNewTeam(
final Player skinnedPlayer,
final Player... sendTo)
{
// This needs to be worked on. If you know how to do it, PR: https://wiki.vg/Protocol#Update_Teams
}
}

View File

@@ -0,0 +1,94 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
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;
import java.lang.reflect.InvocationTargetException;
// Courtesy of Packet Wrapper
public class AbstractPacket {
// The packet we will be modifying
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());
}
/**
* Simulate receiving the current packet from the given sender.
*
* @param sender - the sender.
* @throws RuntimeException If the packet cannot be received.
* @deprecated Misspelled. recieve to receive
* @see #receivePacket(Player)
*/
@Deprecated
public void recievePacket(Player sender) {
try {
ProtocolLibrary.getProtocolManager().receiveClientPacket(sender,
getHandle());
} catch (Exception e) {
throw new RuntimeException("Cannot recieve packet.", e);
}
}
/**
* Simulate receiving the current packet from the given sender.
*
* @param sender - the sender.
* @throws RuntimeException if the packet cannot be received.
*/
public void receivePacket(Player sender) {
try {
ProtocolLibrary.getProtocolManager().receiveClientPacket(sender,
getHandle());
} catch (Exception e) {
throw new RuntimeException("Cannot receive packet.", e);
}
}
}

View File

@@ -0,0 +1,130 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import org.bukkit.inventory.ItemStack;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
public class WrapperPlayClientWindowClick extends AbstractPacket {
public static final PacketType TYPE = PacketType.Play.Client.WINDOW_CLICK;
public WrapperPlayClientWindowClick() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayClientWindowClick(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Window ID.
* <p>
* Notes: the id of the window which was clicked. 0 for player inventory.
*
* @return The current Window ID
*/
public int getWindowId() {
return handle.getIntegers().read(0);
}
/**
* Set Window ID.
*
* @param value - new value.
*/
public void setWindowId(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve Slot.
* <p>
* Notes: the clicked slot. See below.
*
* @return The current Slot
*/
public int getSlot() {
return handle.getIntegers().read(1);
}
/**
* Set Slot.
*
* @param value - new value.
*/
public void setSlot(int value) {
handle.getIntegers().write(1, value);
}
/**
* Retrieve Button.
* <p>
* Notes: the button used in the click. See below.
*
* @return The current Button
*/
public int getButton() {
return handle.getIntegers().read(2);
}
/**
* Set Button.
*
* @param value - new value.
*/
public void setButton(int value) {
handle.getIntegers().write(2, value);
}
/**
* Retrieve Action number.
* <p>
* Notes: a unique number for the action, used for transaction handling (See
* the Transaction packet).
*
* @return The current Action number
*/
public short getActionNumber() {
return handle.getShorts().read(0);
}
/**
* Set Action number.
*
* @param value - new value.
*/
public void setActionNumber(short value) {
handle.getShorts().write(0, value);
}
/**
* Retrieve Clicked item.
*
* @return The current Clicked item
*/
public ItemStack getClickedItem() {
return handle.getItemModifier().read(0);
}
/**
* Set Clicked item.
*
* @param value - new value.
*/
public void setClickedItem(ItemStack value) {
handle.getItemModifier().write(0, value);
}
public InventoryClickType getShift() {
return handle.getEnumModifier(InventoryClickType.class, 5).read(0);
}
public void setShift(InventoryClickType value) {
handle.getEnumModifier(InventoryClickType.class, 5).write(0, value);
}
public enum InventoryClickType {
PICKUP, QUICK_MOVE, SWAP, CLONE, THROW, QUICK_CRAFT, PICKUP_ALL;
}
}

View File

@@ -0,0 +1,111 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.EnumWrappers.ItemSlot;
import java.util.List;
public class WrapperPlayServerEntityEquipment extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.ENTITY_EQUIPMENT;
private List<Equipment> equipment;
public WrapperPlayServerEntityEquipment() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerEntityEquipment(PacketContainer packet) {
super(packet, TYPE);
}
public void read() {
}
public WrapperPlayServerEntityEquipment(PacketContainer packet, int entityId, List<Equipment> equipment) {
super(packet, TYPE);
setEntityID(entityId);
this.equipment = equipment;
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
public ItemSlot getSlot() {
return handle.getItemSlots().read(0);
}
public void setSlot(ItemSlot value) {
if (handle.getItemSlots().getValues().size() > 0) {
handle.getItemSlots().write(0, value);
}
}
/**
* Retrieve Item.
* <p>
* Notes: item in slot format
*
* @return The current Item
*/
public ItemStack getItem() {
return handle.getItemModifier().read(0);
}
/**
* Set Item.
*
* @param value - new value.
*/
public void setItem(ItemStack value) {
if (handle.getItemModifier().getValues().size() > 0) {
handle.getItemModifier().write(0, value);
}
}
}

View File

@@ -0,0 +1,83 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import java.util.List;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
public class WrapperPlayServerEntityMetadata extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.ENTITY_METADATA;
public WrapperPlayServerEntityMetadata() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerEntityMetadata(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Retrieve Metadata.
*
* @return The current Metadata
*/
public List<WrappedWatchableObject> getMetadata() {
return handle.getWatchableCollectionModifier().read(0);
}
/**
* Set Metadata.
*
* @param value - new value.
*/
public void setMetadata(List<WrappedWatchableObject> value) {
handle.getWatchableCollectionModifier().write(0, value);
}
}

View File

@@ -0,0 +1,165 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import java.util.UUID;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
public class WrapperPlayServerNamedEntitySpawn extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.NAMED_ENTITY_SPAWN;
public WrapperPlayServerNamedEntitySpawn() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerNamedEntitySpawn(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Retrieve Player UUID.
* <p>
* Notes: player's UUID
*
* @return The current Player UUID
*/
public UUID getPlayerUUID() {
return handle.getUUIDs().read(0);
}
/**
* Set Player UUID.
*
* @param value - new value.
*/
public void setPlayerUUID(UUID value) {
handle.getUUIDs().write(0, value);
}
/**
* Retrieve the position of the spawned entity as a vector.
*
* @return The position as a vector.
*/
public Vector getPosition() {
return new Vector(getX(), getY(), getZ());
}
/**
* Set the position of the spawned entity using a vector.
*
* @param position - the new position.
*/
public void setPosition(Vector position) {
setX(position.getX());
setY(position.getY());
setZ(position.getZ());
}
public double getX() {
return handle.getDoubles().read(0);
}
public void setX(double value) {
handle.getDoubles().write(0, value);
}
public double getY() {
return handle.getDoubles().read(1);
}
public void setY(double value) {
handle.getDoubles().write(1, value);
}
public double getZ() {
return handle.getDoubles().read(2);
}
public void setZ(double value) {
handle.getDoubles().write(2, value);
}
/**
* Retrieve the yaw of the spawned entity.
*
* @return The current Yaw
*/
public float getYaw() {
return (handle.getBytes().read(0) * 360.F) / 256.0F;
}
/**
* Set the yaw of the spawned entity.
*
* @param value - new yaw.
*/
public void setYaw(float value) {
handle.getBytes().write(0, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve the pitch of the spawned entity.
*
* @return The current pitch
*/
public float getPitch() {
return (handle.getBytes().read(1) * 360.F) / 256.0F;
}
/**
* Set the pitch of the spawned entity.
*
* @param value - new pitch.
*/
public void setPitch(float value) {
handle.getBytes().write(1, (byte) (value * 256.0F / 360.0F));
}
}

View File

@@ -0,0 +1,37 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import java.util.List;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction;
import com.comphenix.protocol.wrappers.PlayerInfoData;
public class WrapperPlayServerPlayerInfo extends AbstractPacket {
public static final PacketType TYPE = PacketType.Play.Server.PLAYER_INFO;
public WrapperPlayServerPlayerInfo() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerPlayerInfo(PacketContainer packet) {
super(packet, TYPE);
}
public PlayerInfoAction getAction() {
return handle.getPlayerInfoAction().read(0);
}
public void setAction(PlayerInfoAction value) {
handle.getPlayerInfoAction().write(0, value);
}
public List<PlayerInfoData> getData() {
return handle.getPlayerInfoDataLists().read(0);
}
public void setData(List<PlayerInfoData> value) {
handle.getPlayerInfoDataLists().write(0, value);
}
}

View File

@@ -0,0 +1,170 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
public class WrapperPlayServerRelEntityMove extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.REL_ENTITY_MOVE;
public WrapperPlayServerRelEntityMove() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerRelEntityMove(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Retrieve DX.
*
* @return The current DX
*/
public double getDx() {
return handle.getShorts().read(0) / 4096D;
}
/**
* Set DX.
*
* @param value - new value.
*/
public void setDx(double value) {
handle.getShorts().write(0, (short) (value * 4096));
}
/**
* Retrieve DY.
*
* @return The current DY
*/
public double getDy() {
return handle.getShorts().read(1) / 4096D;
}
/**
* Set DY.
*
* @param value - new value.
*/
public void setDy(double value) {
handle.getShorts().write(1, (short) (value * 4096));
}
/**
* Retrieve DZ.
*
* @return The current DZ
*/
public double getDz() {
return handle.getShorts().read(2) / 4096D;
}
/**
* Set DZ.
*
* @param value - new value.
*/
public void setDz(double value) {
handle.getShorts().write(2, (short) (value * 4096));
}
/**
* Retrieve the yaw of the current entity.
*
* @return The current Yaw
*/
public float getYaw() {
return (handle.getBytes().read(0) * 360.F) / 256.0F;
}
/**
* Set the yaw of the current entity.
*
* @param value - new yaw.
*/
public void setYaw(float value) {
handle.getBytes().write(0, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve the pitch of the current entity.
*
* @return The current pitch
*/
public float getPitch() {
return (handle.getBytes().read(1) * 360.F) / 256.0F;
}
/**
* Set the pitch of the current entity.
*
* @param value - new pitch.
*/
public void setPitch(float value) {
handle.getBytes().write(1, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve On Ground.
*
* @return The current On Ground
*/
public boolean getOnGround() {
return handle.getBooleans().read(0);
}
/**
* Set On Ground.
*
* @param value - new value.
*/
public void setOnGround(boolean value) {
handle.getBooleans().write(0, value);
}
}

View File

@@ -0,0 +1,170 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
public class WrapperPlayServerRelEntityMoveLook extends AbstractPacket {
public static final PacketType TYPE =
PacketType.Play.Server.REL_ENTITY_MOVE_LOOK;
public WrapperPlayServerRelEntityMoveLook() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerRelEntityMoveLook(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Entity ID.
* <p>
* Notes: entity's ID
*
* @return The current Entity ID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Set Entity ID.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity of the painting that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Retrieve DX.
*
* @return The current DX
*/
public double getDx() {
return handle.getShorts().read(0) / 4096D;
}
/**
* Set DX.
*
* @param value - new value.
*/
public void setDx(double value) {
handle.getShorts().write(0, (short) (value * 4096));
}
/**
* Retrieve DY.
*
* @return The current DY
*/
public double getDy() {
return handle.getShorts().read(1) / 4096D;
}
/**
* Set DY.
*
* @param value - new value.
*/
public void setDy(double value) {
handle.getShorts().write(1, (short) (value * 4096));
}
/**
* Retrieve DZ.
*
* @return The current DZ
*/
public double getDz() {
return handle.getShorts().read(2) / 4096D;
}
/**
* Set DZ.
*
* @param value - new value.
*/
public void setDz(double value) {
handle.getShorts().write(2, (short) (value * 4096));
}
/**
* Retrieve the yaw of the current entity.
*
* @return The current Yaw
*/
public float getYaw() {
return (handle.getBytes().read(0) * 360.F) / 256.0F;
}
/**
* Set the yaw of the current entity.
*
* @param value - new yaw.
*/
public void setYaw(float value) {
handle.getBytes().write(0, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve the pitch of the current entity.
*
* @return The current pitch
*/
public float getPitch() {
return (handle.getBytes().read(1) * 360.F) / 256.0F;
}
/**
* Set the pitch of the current entity.
*
* @param value - new pitch.
*/
public void setPitch(float value) {
handle.getBytes().write(1, (byte) (value * 256.0F / 360.0F));
}
/**
* Retrieve On Ground.
*
* @return The current On Ground
*/
public boolean getOnGround() {
return handle.getBooleans().read(0);
}
/**
* Set On Ground.
*
* @param value - new value.
*/
public void setOnGround(boolean value) {
handle.getBooleans().write(0, value);
}
}

View File

@@ -0,0 +1,314 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import java.util.UUID;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.PacketConstructor;
public class WrapperPlayServerSpawnEntity extends AbstractPacket {
public static final PacketType TYPE = PacketType.Play.Server.SPAWN_ENTITY;
private static PacketConstructor entityConstructor;
public WrapperPlayServerSpawnEntity() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerSpawnEntity(PacketContainer packet) {
super(packet, TYPE);
}
public WrapperPlayServerSpawnEntity(Entity entity, int type, int objectData) {
super(fromEntity(entity, type, objectData), TYPE);
}
// Useful constructor
private static PacketContainer fromEntity(Entity entity, int type,
int objectData) {
if (entityConstructor == null)
entityConstructor =
ProtocolLibrary.getProtocolManager()
.createPacketConstructor(TYPE, entity, type,
objectData);
return entityConstructor.createPacket(entity, type, objectData);
}
/**
* Retrieve entity ID of the Object.
*
* @return The current EID
*/
public int getEntityID() {
return handle.getIntegers().read(0);
}
/**
* Retrieve the entity that will be spawned.
*
* @param world - the current world of the entity.
* @return The spawned entity.
*/
public Entity getEntity(World world) {
return handle.getEntityModifier(world).read(0);
}
/**
* Retrieve the entity that will be spawned.
*
* @param event - the packet event.
* @return The spawned entity.
*/
public Entity getEntity(PacketEvent event) {
return getEntity(event.getPlayer().getWorld());
}
/**
* Set entity ID of the Object.
*
* @param value - new value.
*/
public void setEntityID(int value) {
handle.getIntegers().write(0, value);
}
public UUID getUniqueId() {
return handle.getUUIDs().read(0);
}
public void setUniqueId(UUID value) {
handle.getUUIDs().write(0, value);
}
/**
* Retrieve the x position of the object.
* <p>
* Note that the coordinate is rounded off to the nearest 1/32 of a meter.
*
* @return The current X
*/
public double getX() {
return handle.getDoubles().read(0);
}
/**
* Set the x position of the object.
*
* @param value - new value.
*/
public void setX(double value) {
handle.getDoubles().write(0, value);
}
/**
* Retrieve the y position of the object.
* <p>
* Note that the coordinate is rounded off to the nearest 1/32 of a meter.
*
* @return The current y
*/
public double getY() {
return handle.getDoubles().read(1);
}
/**
* Set the y position of the object.
*
* @param value - new value.
*/
public void setY(double value) {
handle.getDoubles().write(1, value);
}
/**
* Retrieve the z position of the object.
* <p>
* Note that the coordinate is rounded off to the nearest 1/32 of a meter.
*
* @return The current z
*/
public double getZ() {
return handle.getDoubles().read(2);
}
/**
* Set the z position of the object.
*
* @param value - new value.
*/
public void setZ(double value) {
handle.getDoubles().write(2, value);
}
/**
* Retrieve the optional speed x.
* <p>
* This is ignored if {@link #getObjectData()} is zero.
*
* @return The optional speed x.
*/
public double getOptionalSpeedX() {
return handle.getIntegers().read(1) / 8000.0D;
}
/**
* Set the optional speed x.
*
* @param value - new value.
*/
public void setOptionalSpeedX(double value) {
handle.getIntegers().write(1, (int) (value * 8000.0D));
}
/**
* Retrieve the optional speed y.
* <p>
* This is ignored if {@link #getObjectData()} is zero.
*
* @return The optional speed y.
*/
public double getOptionalSpeedY() {
return handle.getIntegers().read(2) / 8000.0D;
}
/**
* Set the optional speed y.
*
* @param value - new value.
*/
public void setOptionalSpeedY(double value) {
handle.getIntegers().write(2, (int) (value * 8000.0D));
}
/**
* Retrieve the optional speed z.
* <p>
* This is ignored if {@link #getObjectData()} is zero.
*
* @return The optional speed z.
*/
public double getOptionalSpeedZ() {
return handle.getIntegers().read(3) / 8000.0D;
}
/**
* Set the optional speed z.
*
* @param value - new value.
*/
public void setOptionalSpeedZ(double value) {
handle.getIntegers().write(3, (int) (value * 8000.0D));
}
/**
* Retrieve the pitch.
*
* @return The current pitch.
*/
public float getPitch() {
return (handle.getIntegers().read(4) * 360.F) / 256.0F;
}
/**
* Set the pitch.
*
* @param value - new pitch.
*/
public void setPitch(float value) {
handle.getIntegers().write(4, (int) (value * 256.0F / 360.0F));
}
/**
* Retrieve the yaw.
*
* @return The current Yaw
*/
public float getYaw() {
return (handle.getIntegers().read(5) * 360.F) / 256.0F;
}
/**
* Set the yaw of the object spawned.
*
* @param value - new yaw.
*/
public void setYaw(float value) {
handle.getIntegers().write(5, (int) (value * 256.0F / 360.0F));
}
/**
* Retrieve the type of object.
*
* @return The current Type
*/
public EntityType getType() {
return handle.getEntityTypeModifier().read(0);
}
/**
* Set the type of object.
*
* @param value - new value.
*/
public void setType(EntityType value) {
handle.getEntityTypeModifier().write(0, value);
}
/**
* Retrieve object data.
* <p>
* The content depends on the object type:
* <table border="1" cellpadding="4">
* <tr>
* <th>Object Type:</th>
* <th>Name:</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>ITEM_FRAME</td>
* <td>Orientation</td>
* <td>0-3: South, West, North, East</td>
* </tr>
* <tr>
* <td>FALLING_BLOCK</td>
* <td>Block Type</td>
* <td>BlockID | (Metadata << 0xC)</td>
* </tr>
* <tr>
* <td>Projectiles</td>
* <td>Entity ID</td>
* <td>The entity ID of the thrower</td>
* </tr>
* <tr>
* <td>Splash Potions</td>
* <td>Data Value</td>
* <td>Potion data value.</td>
* </tr>
* </table>
*
* @return The current object Data
*/
public int getObjectData() {
return handle.getIntegers().read(6);
}
/**
* Set object Data.
* <p>
* The content depends on the object type. See {@link #getObjectData()} for
* more information.
*
* @param value - new object data.
*/
public void setObjectData(int value) {
handle.getIntegers().write(6, value);
}
}

View File

@@ -0,0 +1,61 @@
package io.github.fisher2911.hmccosmetics.packet.wrappers;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
public class WrapperPlayServerWindowItems extends AbstractPacket {
public static final PacketType TYPE = PacketType.Play.Server.WINDOW_ITEMS;
public WrapperPlayServerWindowItems() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerWindowItems(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve Window ID.
* <p>
* Notes: the id of window which items are being sent for. 0 for player
* inventory.
*
* @return The current Window ID
*/
public int getWindowId() {
return handle.getIntegers().read(0);
}
/**
* Set Window ID.
*
* @param value - new value.
*/
public void setWindowId(int value) {
handle.getIntegers().write(0, value);
}
/**
* Retrieve Slot data.
*
* @return The current Slot data
*/
public List<ItemStack> getSlotData() {
return handle.getItemListModifier().read(0);
}
/**
* Set Slot data.
*
* @param value - new value.
*/
public void setSlotData(List<ItemStack> value) {
handle.getItemListModifier().write(0, value);
}
}

View File

@@ -1,35 +1,32 @@
package io.github.fisher2911.hmccosmetics.user;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.database.Database;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import io.github.retrooper.packetevents.util.SpigotReflectionUtil;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
public class Backpack {
private final HMCCosmetics plugin;
private final int armorStandID;
private final int particleCount = HMCCosmetics.getPlugin(HMCCosmetics.class).getSettings().getCosmeticSettings().getParticleCount();
private final List<Integer> particleIDS = new ArrayList<>();
public Backpack(HMCCosmetics plugin, int armorStandID) {
this.plugin = plugin;
this.armorStandID = armorStandID;
for (int i = 0; i < particleCount; i++) {
particleIDS.add(SpigotReflectionUtil.generateEntityId());
}
}
public void spawn(BaseUser<?> owner, Player other, Location location, Settings settings) {
@@ -38,6 +35,7 @@ public class Backpack {
this.spawnForOther(owner, other, location);
return;
}
this.updateIds(owner);
this.spawnForSelf(other, location);
}
@@ -49,7 +47,7 @@ public class Backpack {
if (currentSize == particleCount) return;
if (currentSize < particleCount) {
for (int i = currentSize; i < particleCount; i++) {
this.particleIDS.add(SpigotReflectionUtil.generateEntityId());
this.particleIDS.add(Database.getNextEntityId());
}
return;
}
@@ -57,9 +55,11 @@ public class Backpack {
}
private void spawnForOther(BaseUser<?> owner, Player other, Location location) {
PacketManager.sendEntitySpawnPacket(location, this.armorStandID, EntityTypes.ARMOR_STAND, other);
PacketManager.sendEntitySpawnPacket(location, this.armorStandID, EntityType.ARMOR_STAND, other);
PacketManager.sendArmorStandMetaContainer(this.armorStandID, other);
PacketManager.sendRidingPacket(owner.getEntityId(), this.armorStandID, other);
//plugin.getLogger().info("Sent spawnForOther. Mount: " + owner.getEntityId() + " | Armorstand: " + this.armorStandID);
//PacketManager.sendRidingPacket(owner.getEntityId(), new int[]{this.armorStandID}, other);
}
private void spawnForSelf(Player other, Location location) {
@@ -67,13 +67,13 @@ public class Backpack {
PacketManager.sendEntityNotLivingSpawnPacket(
location,
id,
EntityTypes.AREA_EFFECT_CLOUD,
EntityType.AREA_EFFECT_CLOUD,
UUID.randomUUID(),
0,
other
);
}
PacketManager.sendEntitySpawnPacket(location, this.armorStandID, EntityTypes.ARMOR_STAND, other);
PacketManager.sendEntitySpawnPacket(location, this.armorStandID, EntityType.ARMOR_STAND, other);
}
public void despawn(Player player) {
@@ -96,37 +96,28 @@ public class Backpack {
final boolean isSelf = owner.getId().equals(other.getUniqueId());
final boolean firstPersonMode = settings.getCosmeticSettings().isFirstPersonBackpackMode();
final ArmorItem.Type type = isSelf && firstPersonMode ? ArmorItem.Type.SELF_BACKPACK : ArmorItem.Type.BACKPACK;
final List<com.github.retrooper.packetevents.protocol.player.Equipment> equipment = new ArrayList<>();
final int lookDownPitch = settings.getCosmeticSettings().getLookDownPitch();
final boolean hidden = !owner.shouldShow(other);
ItemStack itemStack = owner.getPlayerArmor().getItem(type).getItemStack(ArmorItem.Status.APPLIED);
Equipment equip = new Equipment();
final boolean isLookingDown =
!firstPersonMode &&
isSelf &&
lookDownPitch != -1 &&
owner.isFacingDown(location, lookDownPitch);
if (hidden || isLookingDown) {
equipment.add(new com.github.retrooper.packetevents.protocol.player.Equipment(
EquipmentSlot.HELMET,
new com.github.retrooper.packetevents.protocol.item.ItemStack.Builder().
type(ItemTypes.AIR).
build()
));
PacketManager.sendEquipmentPacket(equipment, this.armorStandID, other);
equip.setItem(EquipmentSlot.HEAD, new ItemStack(Material.AIR));
PacketManager.sendEquipmentPacket(equip, this.armorStandID, other);
return;
}
final com.github.retrooper.packetevents.protocol.item.ItemStack itemStack =
SpigotConversionUtil.fromBukkitItemStack(owner.getPlayerArmor().getItem(type).getItemStack(ArmorItem.Status.APPLIED));
equipment.add(new com.github.retrooper.packetevents.protocol.player.Equipment(
EquipmentSlot.HELMET,
itemStack
));
PacketManager.sendEquipmentPacket(equipment, this.armorStandID, other);
equip.setItem(EquipmentSlot.HEAD, itemStack);
PacketManager.sendEquipmentPacket(equip, this.armorStandID, other);
PacketManager.sendArmorStandMetaContainer(this.armorStandID, other);
PacketManager.sendRotationPacket(this.armorStandID, location, false, other);
PacketManager.sendLookPacket(this.armorStandID, location, other);
if (!isSelf) {
if (!isSelf || !firstPersonMode || this.particleIDS.size() == 0) {
PacketManager.sendRidingPacket(owner.getEntityId(), this.armorStandID, other);
//plugin.getLogger().info("Sent updateBackpack. Mount: " + owner.getEntityId() + " | Armorstand: " + this.armorStandID);
return;
}
for (int i = 0; i < this.particleIDS.size(); i++) {
@@ -139,6 +130,6 @@ public class Backpack {
}
}
PacketManager.sendRidingPacket(particleIDS.get(particleIDS.size() - 1), this.armorStandID, other);
//plugin.getLogger().info("Sent updateBackpack Other. Mount: " + owner.getEntityId() + " | Armorstand: " + this.armorStandID);
}
}

View File

@@ -1,11 +1,11 @@
package io.github.fisher2911.hmccosmetics.user;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.BalloonItem;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.ModelEngineHook;
import io.github.fisher2911.hmccosmetics.hook.entity.BalloonEntity;
@@ -47,7 +47,7 @@ public abstract class BaseUser<T> {
if (!HookManager.getInstance().isEnabled(ModelEngineHook.class)) {
this.balloon = null;
} else {
this.balloon = new BalloonEntity(UUID.randomUUID(), -1, EntityType.PUFFERFISH);
this.balloon = new BalloonEntity(entityIds.balloon(), getLocation());
}
}
@@ -139,7 +139,7 @@ public abstract class BaseUser<T> {
this.balloon.addPlayerToModel(other, id);
}
final int balloonId = this.getBalloonId();
PacketManager.sendEntitySpawnPacket(actual, balloonId, EntityTypes.PUFFERFISH, other);
PacketManager.sendEntitySpawnPacket(actual, balloonId, EntityType.PUFFERFISH, other);
PacketManager.sendInvisibilityPacket(balloonId, other);
PacketManager.sendLeashPacket(balloonId, this.getEntityId(), other);
this.updateBalloon(other, location, settings);

View File

@@ -1,17 +1,25 @@
package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Equipment {
private static final EquipmentSlot[] VALUES = EquipmentSlot.values();
private final Map<EquipmentSlot, ItemStack> equipment = new EnumMap<>(EquipmentSlot.class);
private final HashMap<EquipmentSlot, ItemStack> equipment = new HashMap<>();
public Equipment() {
}
@@ -25,6 +33,24 @@ public class Equipment {
return equipment;
}
public static Equipment fromEntityEquipment(@Nullable final Player player) {
if (player == null) return new Equipment();
final Equipment equipment = new Equipment();
for (final EquipmentSlot slot : VALUES) {
equipment.setItem(slot, player.getInventory().getItem(slot));
}
return equipment;
}
public static Equipment fromEntityEquipment(@Nullable final User user) {
if (user == null) return new Equipment();
final Equipment equipment = new Equipment();
for (final EquipmentSlot slot : VALUES) {
equipment.setItem(slot, user.getPlayer().getInventory().getItem(slot));
}
return equipment;
}
@Nullable
public ItemStack getItem(final EquipmentSlot slot) {
return this.equipment.get(slot);
@@ -34,4 +60,19 @@ public class Equipment {
this.equipment.put(slot, itemStack);
}
public EquipmentSlot[] values() {
return VALUES;
}
public Set<EquipmentSlot> keys() {
return equipment.keySet();
}
public void removeSlot(EquipmentSlot slot) {
equipment.remove(slot);
}
public void clear() {
equipment.clear();
}
}

View File

@@ -37,6 +37,10 @@ public class User extends BaseUser<UUID> {
}
public @Nullable Player getPlayer() {
// Forwhatever reason, this was sometimes null. Just a fallback in case
if (this.playerReference == null) {
return Bukkit.getPlayer(this.getId());
}
Player player = this.playerReference.get();
if (player == null) {
player = Bukkit.getPlayer(this.getId());

View File

@@ -1,5 +1,6 @@
package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.wrappers.EnumWrappers;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;
import io.github.fisher2911.hmccosmetics.api.event.CosmeticChangeEvent;
@@ -13,6 +14,7 @@ import io.github.fisher2911.hmccosmetics.message.Placeholder;
import io.github.fisher2911.hmccosmetics.message.Translation;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.task.InfiniteTask;
import io.github.fisher2911.hmccosmetics.util.PlayerUtils;
import io.github.fisher2911.hmccosmetics.util.Utils;
import io.github.fisher2911.hmccosmetics.util.builder.ItemBuilder;
import org.bukkit.Bukkit;
@@ -105,18 +107,14 @@ public class UserManager {
this.sendUpdatePacket(
user,
other,
this.getItemList(
user,
user.getEquipment(),
Collections.emptySet()
)
getItemList(user)
);
}
public void updateCosmetics(final BaseUser<?> user) {
this.sendUpdatePacket(
user,
this.getItemList(user, user.getEquipment(), Collections.emptySet())
getItemList(user)
);
}
@@ -148,18 +146,24 @@ public class UserManager {
return itemStack;
}
public List<com.github.retrooper.packetevents.protocol.player.Equipment> getItemList(
public Equipment getItemList(
final BaseUser<?> user
) {
return getItemList(user, user.getEquipment(), Collections.emptySet());
}
public Equipment getItemList(
final BaseUser<?> user,
final Equipment equipment,
final Set<ArmorItem.Type> ignored
) {
final PlayerArmor armor = user.getPlayerArmor();
final List<com.github.retrooper.packetevents.protocol.player.Equipment> items = new ArrayList<>();
for (final ArmorItem.Type type : ArmorItem.Type.values()) {
final EquipmentSlot slot = type.getSlot();
if (slot == null) continue;
if (ignored.contains(type)) {
items.add(PacketManager.getEquipment(equipment.getItem(slot), slot));
Equipment item = PlayerUtils.getEquipment(equipment.getItem(slot), slot);
equipment.setItem(slot, item.getItem(slot));
continue;
}
final ItemStack wearing = Utils.replaceIfNull(equipment.getItem(slot), new ItemStack(Material.AIR));
@@ -169,17 +173,9 @@ public class UserManager {
ArmorItem.Status.APPLIED,
slot
);
items.add(PacketManager.getEquipment(itemStack, slot));
equipment.setItem(slot, itemStack);
}
return items;
}
public List<com.github.retrooper.packetevents.protocol.player.Equipment> getEmptyItemList() {
final List<com.github.retrooper.packetevents.protocol.player.Equipment> items = new ArrayList<>();
for (final EquipmentSlot slot : EquipmentSlot.values()) {
items.add(PacketManager.getEquipment(new ItemStack(Material.AIR), slot));
}
return items;
return equipment;
}
public void setItem(final BaseUser<?> user, final ArmorItem armorItem, final boolean sendPacket) {
@@ -262,7 +258,8 @@ public class UserManager {
public void removeAll() {
for (final var user : this.userMap.values()) {
user.despawnAttached();
// server is shutting down anyways when this is called
//user.despawnAttached();
}
this.userMap.clear();
@@ -286,39 +283,42 @@ public class UserManager {
final ArmorItem.Type type) {
final EquipmentSlot slot = type.getSlot();
final ItemStack itemStack = this.getCosmeticItem(armorItem, wearing, ArmorItem.Status.APPLIED, slot);
final List<com.github.retrooper.packetevents.protocol.player.Equipment> itemList = new ArrayList<>();
itemList.add(PacketManager.getEquipment(itemStack, slot));
this.sendUpdatePacket(user, itemList);
//final List<Equipment> itemList = new ArrayList<>();
//itemList.add(PacketManager.getEquipment(itemStack, slot));
Equipment equip = new Equipment();
equip.setItem(slot, itemStack);
this.sendUpdatePacket(user, equip);
}
/**
* Sends a packet to a player "updating" their equipment.
* @param user The user having their equipment being updated.
* @param equipment The equipment that is being set on the player.
*/
public void sendUpdatePacket(
final BaseUser<?> user,
List<com.github.retrooper.packetevents.protocol.player.Equipment> items
Equipment equipment
) {
// final Player player = user.getPlayer();
// if (player == null) return;
final Location location = user.getLocation();
if (location == null) return;
final int entityId = user.getEntityId();
if (items.isEmpty()) return;
if (equipment == null) return;
for (final User otherUser : this.userMap.values()) {
final Player other = otherUser.getPlayer();
if (other == null) continue;
if (!user.shouldShow(other)) continue;
if (!this.settings.getCosmeticSettings().isInViewDistance(location, other.getLocation())) continue;
user.updateBackpack(other, this.settings);
PacketManager.sendEquipmentPacket(
items,
entityId,
other
);
PacketManager.sendEquipmentPacket(equipment, entityId, other);
}
}
public void sendUpdatePacket(
final BaseUser<?> user,
final Player other,
List<com.github.retrooper.packetevents.protocol.player.Equipment> items
Equipment equipment
) {
// final Player player = user.getPlayer();
// if (player == null) return;
@@ -328,10 +328,6 @@ public class UserManager {
if (other == null) return;
if (!user.shouldShow(other)) return;
if (!this.settings.getCosmeticSettings().isInViewDistance(location, other.getLocation())) return;
PacketManager.sendEquipmentPacket(
items,
entityId,
other
);
PacketManager.sendEquipmentPacket(equipment, entityId, other);
}
}

View File

@@ -1,6 +1,6 @@
package io.github.fisher2911.hmccosmetics.user;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.comphenix.protocol.wrappers.Vector3F;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
@@ -10,8 +10,13 @@ import io.github.fisher2911.hmccosmetics.task.SupplierTask;
import io.github.fisher2911.hmccosmetics.task.Task;
import io.github.fisher2911.hmccosmetics.task.TaskChain;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.Nullable;
@@ -28,6 +33,8 @@ public class Wardrobe extends User {
private boolean active;
private boolean spawned;
private Location currentLocation;
private Location enterLocation;
private GameMode originalGamemode;
public Wardrobe(
final HMCCosmetics plugin,
@@ -42,11 +49,27 @@ public class Wardrobe extends User {
this.ownerUUID = ownerUUID;
this.active = active;
this.wardrobe = this;
this.originalGamemode = GameMode.SURVIVAL;
}
public void spawnFakePlayer(final Player viewer) {
final UserManager userManager = this.plugin.getUserManager();
final WardrobeSettings settings = this.plugin.getSettings().getWardrobeSettings();
this.originalGamemode = viewer.getGameMode();
this.enterLocation = viewer.getLocation();
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
PacketManager.sendEntitySpawnPacket(
settings.getViewerLocation(),
this.entityIds.wardrobeViewer(),
EntityType.ARMOR_STAND,
viewer
);
PacketManager.sendFakePlayerInfoPacket(viewer, this.getId(), viewer);
PacketManager.sendInvisibilityPacket(
this.entityIds.wardrobeViewer(),
viewer
);
});
Bukkit.getScheduler().runTaskLaterAsynchronously(
this.plugin,
@@ -54,20 +77,15 @@ public class Wardrobe extends User {
if (settings.inDistanceOfStatic(viewer.getLocation())) {
this.currentLocation = settings.getWardrobeLocation();
userManager.get(viewer.getUniqueId()).ifPresent(user -> {
userManager.sendUpdatePacket(user, userManager.getEmptyItemList());
userManager.sendUpdatePacket(user, userManager.getItemList(user));
user.despawnAttached();
user.despawnBalloon();
});
PacketManager.sendEntitySpawnPacket(
settings.getViewerLocation(),
this.entityIds.wardrobeViewer(),
EntityTypes.ARMOR_STAND,
viewer
);
PacketManager.sendCameraPacket(
this.entityIds.wardrobeViewer(),
viewer
);
// This makes the player viewing the wardrobe invisible
PacketManager.sendInvisibilityPacket(
this.entityIds.wardrobeViewer(),
viewer
@@ -77,10 +95,15 @@ public class Wardrobe extends User {
settings.getViewerLocation(),
viewer
);
// This make the person viewing the wardrobe invisible
PacketManager.sendInvisibilityPacket(
viewer.getEntityId(),
viewer
);
PacketManager.sendGameModeChange(
viewer,
GameMode.SPECTATOR
);
this.hidePlayer();
this.setActive(true);
} else if (this.currentLocation == null) {
@@ -91,8 +114,8 @@ public class Wardrobe extends User {
return;
}
final int entityId = this.getEntityId();
PacketManager.sendFakePlayerInfoPacket(viewer, this.getId(), viewer);
PacketManager.sendFakePlayerSpawnPacket(this.currentLocation, this.getId(), entityId, viewer);
PacketManager.sendNewTeam(viewer, viewer);
PacketManager.sendLookPacket(entityId, this.currentLocation, viewer);
PacketManager.sendRotationPacket(entityId, this.currentLocation, true, viewer);
PacketManager.sendPlayerOverlayPacket(entityId, viewer);
@@ -110,9 +133,8 @@ public class Wardrobe extends User {
);
}
});
// PacketManager.sendEntitySpawnPacket(this.currentLocation, this.getEntityId(), EntityTypes.ZOMBIE, viewer);
this.spawned = true;
this.startSpinTask(viewer);
this.updateTask(viewer);
},
settings.getSpawnDelay()
);
@@ -137,6 +159,9 @@ public class Wardrobe extends User {
viewer
);
this.showPlayer(this.plugin.getUserManager());
PacketManager.sendGameModeChange(
viewer, originalGamemode
);
final Collection<ArmorItem> armorItems = new ArrayList<>(this.getPlayerArmor().getArmorItems());
if (settings.isApplyCosmeticsOnClose()) {
final Optional<User> optionalUser = userManager.get(this.ownerUUID);
@@ -167,32 +192,51 @@ public class Wardrobe extends User {
},
true
).chain(
() -> viewer.teleport(settings.getLeaveLocation())
() -> {
if (settings.isReturnLastLocation()) {
viewer.teleport(enterLocation);
} else {
viewer.teleport(settings.getLeaveLocation());
}
}
).chain(() -> {
this.despawnAttached();
this.despawnBalloon();
}, true).
execute();
}, true)
.execute();
},
settings.getDespawnDelay()
);
}
private void startSpinTask(final Player player) {
/**
* Used as an updater to send packets and other information to the player while they are in the wardrobe
* @param player
*/
private void updateTask(final Player player) {
final AtomicInteger data = new AtomicInteger();
final int rotationSpeed = this.plugin.getSettings().getWardrobeSettings().getRotationSpeed();
final boolean equipPumpkin = this.plugin.getSettings().getWardrobeSettings().isEquipPumpkin();
final int entityId = this.getEntityId();
final Task task = new SupplierTask(
() -> {
if (this.currentLocation == null) return;
final Location location = this.currentLocation.clone();
final int yaw = data.get();
location.setYaw(yaw);
PacketManager.sendLookPacket(entityId, location, player);
this.updateOutsideCosmetics(player, location, this.plugin.getSettings());
location.setYaw(this.getNextYaw(yaw - 30, rotationSpeed));
PacketManager.sendRotationPacket(entityId, location, true, player);
data.set(this.getNextYaw(yaw, rotationSpeed));
// Need to put the pumpkin here because it will be overriden otherwise ~ LoJoSho
if (equipPumpkin) {
Equipment equipment = new Equipment();
equipment.setItem(EquipmentSlot.HEAD, new ItemStack(Material.CARVED_PUMPKIN));
PacketManager.sendEquipmentPacket(equipment, player.getEntityId(), player);
}
},
() -> !this.spawned || this.currentLocation == null
);
@@ -200,8 +244,12 @@ public class Wardrobe extends User {
}
private int getNextYaw(final int current, final int rotationSpeed) {
if (current + rotationSpeed > 179) return -179;
return current + rotationSpeed;
int nextYaw = current + rotationSpeed;
if (nextYaw > 179) {
nextYaw = (current + rotationSpeed) - 358;
return nextYaw;
}
return nextYaw;
}
@Override

View File

@@ -0,0 +1,81 @@
package io.github.fisher2911.hmccosmetics.util;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import io.github.fisher2911.hmccosmetics.user.Equipment;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
public class PlayerUtils {
public static WrappedSignedProperty getSkin(Player player) {
WrappedSignedProperty skinData = WrappedGameProfile.fromPlayer(player).getProperties()
.get("textures").stream().findAny().orElse(null);
if (skinData == null)
throw new RuntimeException("Missing skin data");
return new WrappedSignedProperty("textures", skinData.getValue(), skinData.getSignature());
}
/**
* Gets the equipment of a slot
* @param itemStack the ItemStack of a slot
* @param slot the slot to look at
* @return returns the equipment at a slot
*/
// It works now, need to redo this sytem sometime in the future...
public static Equipment getEquipment(
final ItemStack itemStack,
final org.bukkit.inventory.EquipmentSlot slot
) {
Equipment equip = new Equipment();
equip.setItem(slot, itemStack);
return equip;
}
/*
public static EquipmentSlot fromBukkitSlot(final org.bukkit.inventory.EquipmentSlot slot) {
return switch (slot) {
case HEAD -> EquipmentSlot.HELMET;
case CHEST -> EquipmentSlot.CHEST_PLATE;
case LEGS -> EquipmentSlot.LEGGINGS;
case FEET -> EquipmentSlot.BOOTS;
case HAND -> EquipmentSlot.MAIN_HAND;
case OFF_HAND -> EquipmentSlot.OFF_HAND;
};
}
*/
/**
* Converts from the Bukkit item slots to ProtocolLib item slots. Will produce a null if an improper bukkit item slot is sent through
* @param slot The BUKKIT item slot to convert.
* @return The ProtocolLib item slot that is returned
*/
public static EnumWrappers.ItemSlot itemBukkitSlot(final EquipmentSlot slot) {
return switch (slot) {
case HEAD -> EnumWrappers.ItemSlot.HEAD;
case CHEST -> EnumWrappers.ItemSlot.CHEST;
case LEGS -> EnumWrappers.ItemSlot.LEGS;
case FEET -> EnumWrappers.ItemSlot.FEET;
case HAND -> EnumWrappers.ItemSlot.MAINHAND;
case OFF_HAND -> EnumWrappers.ItemSlot.OFFHAND;
};
}
/**
* Converts a bukkit gamemode into an integer for use in packets
* @param gamemode Bukkit gamemode to convert.
* @return int of the gamemode
*/
public static int convertGamemode(final GameMode gamemode) {
return switch (gamemode) {
case SURVIVAL -> 0;
case CREATIVE -> 1;
case ADVENTURE -> 2;
case SPECTATOR -> 3;
};
}
}

View File

@@ -5,6 +5,10 @@ cosmetic-settings:
require-empty-chest-plate: false
require-empty-pants: false
require-empty-boots: false
# Disable if you don't want to use the first person backpack system
# See the wiki for more information
# This option has been temporarily disabled in the beta releases.
first-person-backpack-mode: false
# The pitch the player must look down for the backpack to be removed
# Set to -1 for no removal
@@ -38,6 +42,10 @@ wardrobe:
despawn-delay: 40
# if cosmetics that the user have permissions for should be applied on close of wardrobe
apply-cosmetics-on-close: true
# Applies a pumpkin for an overlay of the player while in the wardrobe.
equip-pumpkin: false
# Rather than having a set exit location, this will send the player back to where they entered the wardrobe.
return-last-location: false
open-sound:
sound: # Play a sound
name: "minecraft:block.chain.break"

View File

@@ -0,0 +1,28 @@
1:
material: PAPER
name: "<blue>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 8
type: SELF_BACKPACK
permission: ""
id: backpack_self
2:
material: PAPER
name: "<blue>Future Wings"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 10
type: SELF_BACKPACK
permission: ""
id: future_wings_self

View File

@@ -11,7 +11,7 @@ items:
locked-lore: # Lore displayed when the player does not have the correct permission.
- "<red>You do not own this item!"
applied-lore: # Lore displayed when the player has the cosmetic in their inventory.
- "<gray>My awesome <rainbow>Colorful Hat</rainbow>!"
- "<gray>My awesome <rainbow>Colorful Hat</rainbow>!"
amount: 1
model-data: 2 # CustomModelData Number
type: HAT
@@ -36,10 +36,32 @@ items:
- "<red>You do not own this item!"
amount: 1
model-data: 4
action:
equip:
any:
set-cosmetics: backpack_self
type: BACKPACK
permission: ""
id: backpack
3:
material: PAPER
name: "<#d24c9f>Future Wings"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 9
action:
equip:
any:
set-cosmetics: future_wings_self
type: BACKPACK
permission: ""
id: future_wings
4:
material: PAPER
name: "<blue>Lantern Cosmetic"
lore:
@@ -53,7 +75,7 @@ items:
type: OFF_HAND
permission: ""
id: lantern_cosmetic
4:
5:
material: PAPER
name: "<blue>Baseball Hat"
lore:
@@ -67,7 +89,49 @@ items:
type: HAT
permission: ""
id: baseball_hat
5:
6:
material: PAPER
name: "<green>Frog Hat"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 11
type: HAT
permission: ""
id: frog_hat
7:
material: PAPER
name: "<#d24c9f>Jetpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 12
type: BACKPACK
permission: ""
id: jetpack
10:
material: PAPER
name: "<#d24c9f>Hammer"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 13
type: OFF_HAND
permission: ""
id: hammer
11:
material: DIAMOND_CHESTPLATE
name: "<blue>Cosmetic Chestplate"
lore:
@@ -80,7 +144,7 @@ items:
type: CHEST_PLATE
permission: ""
id: chestplate
6:
12:
material: DIAMOND_LEGGINGS
name: "<blue>Cosmetic Leggings"
lore:
@@ -93,7 +157,7 @@ items:
type: PANTS
permission: ""
id: pants
7:
13:
material: DIAMOND_BOOTS
name: "<blue>Cosmetic Boots"
lore:
@@ -106,7 +170,7 @@ items:
type: BOOTS
permission: ""
id: boots
10:
14:
material: PAPER
name: "<blue>Balloon"
lore:

View File

@@ -1,193 +0,0 @@
title: "<white>" # GUI Title
rows: 5 # Rows in the GUI
items:
1: # GUI Slot number
material: LEATHER_HORSE_ARMOR # Also supports Oraxen items! Format: "oraxen:item_name"
name: "<rainbow>Colorful Hat</rainbow>"
lore: # Lore displayed when the player owns the item
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore: # Lore displayed when the player does not have the correct permission.
- "<red>You do not own this item!"
amount: 1
model-data: 2 # CustomModelData Number
type: HAT
dyeable: true # Enables dyeable item feature
color: # Sets default color for item. Uses RGB format.
red: 5
green: 230
blue: 100
action: # See how the action system works on the wiki
any:
open-menu: dye-menu
permission: "cosmetics.colorful_hat" # Can be anything you want.
id: colorful_hat # Internal identifier. Can be anything you want.
2:
material: PAPER
name: "<blue>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 4
type: BACKPACK
permission: ""
id: backpack
action:
# when the action should be run
# equip = when a cosmetic is equipped
# remove = when a cosmetic is removed
# any all = default, does not need to be specified
equip:
# click type
any:
send-message: "on equip"
remove:
any:
send-message: "on-remove"
any:
# send a message
send-message: "Test first message"
# send a command, format is <sender:command>
# senders can be player or console
send-command: "player:give %player% diamond"
# list of messages
send-messages:
- "Message 1"
- "Message 2"
# list of commands
send-commands:
- "player:help"
- "console:give %player% gold_ingot"
# set items in the specified slots in the inventory
# works with all actions
# sets items in the next inventory if open-menu is specified
set-items:
12:
material: PAPER
name: "<red>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 4
type: BACKPACK
permission: ""
id: backpack
action:
any:
send-message: "It worked?"
set-items:
12:
material: PAPER
name: "<rainbow>Backpack"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 4
type: BACKPACK
permission: ""
id: backpack
3:
material: PAPER
name: "<blue>Lantern Cosmetic"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 5
type: OFF_HAND
permission: ""
id: lantern_cosmetic
4:
material: PAPER
name: "<blue>Baseball Hat"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
model-data: 6
type: HAT
permission: ""
id: baseball_hat
5:
material: DIAMOND_CHESTPLATE
name: "<blue>Cosmetic Chestplate"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: CHEST_PLATE
permission: ""
id: chestplate
6:
material: DIAMOND_LEGGINGS
name: "<blue>Cosmetic Leggings"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: PANTS
permission: ""
id: pants
7:
material: DIAMOND_BOOTS
name: "<blue>Cosmetic Boots"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: BOOTS
permission: ""
id: boots
37:
material: PAPER
name: "<#40B7D6>Previous Page"
amount: 1
model-data: 1
action:
any:
open-menu: menu-2
40:
material: PAPER
name: "<rainbow>Customization Menu</rainbow>"
amount: 1
model-data: 3
action:
any:
open-menu: dye-menu
43:
material: PAPER
name: "<#40B7D6>Next Page"
amount: 1
model-data: 2
action:
any:
open-menu: menu-2

2
gradle.properties Normal file
View File

@@ -0,0 +1,2 @@
copyJar=false
hibiscusmc_plugin_path=""