Commit ad82d280 authored by Ashijin's avatar Ashijin
Browse files

1.19.3 support, cleaned up dependencies

parent ea5c8224
......@@ -4,12 +4,12 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.lumine</groupId>
<artifactId>MCCosmetics-API</artifactId>
<version>0.8.0-SNAPSHOT</version>
<version>0.11.0</version>
<dependencies>
<dependency>
<groupId>io.lumine</groupId>
<artifactId>LumineUtils</artifactId>
<version>1.18-SNAPSHOT</version>
<version>1.19-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
......@@ -38,10 +38,6 @@
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>sk89q-repo</id>
<url>https://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>md_5-snapshots</id>
<url>https://repo.md-5.net/content/repositories/snapshots/</url>
......@@ -50,10 +46,6 @@
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>filoghost-repo</id>
<url>https://ci.filoghost.me/plugin/repository/everything/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
......
......@@ -64,6 +64,12 @@
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.lumine</groupId>
<artifactId>MCCosmetics-v1_19_R2</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
......
......@@ -82,13 +82,9 @@
</build>
<repositories>
<repository>
<id>nexus</id>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>lumine-public</id>
<url>https://mvn.lumine.io/repository/maven-public/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
......@@ -113,10 +109,6 @@
<updatePolicy>never</updatePolicy>
</releases>
</repository> -->
<repository>
<id>sk89q-repo</id>
<url>https://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>md_5-public</id>
<url>https://repo.md-5.net/content/groups/public/</url>
......@@ -129,10 +121,6 @@
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>filoghost-repo</id>
<url>https://ci.filoghost.me/plugin/repository/everything/</url>
</repository>
<repository>
<id>CodeMC</id>
<url>https://repo.codemc.org/repository/maven-public</url>
......@@ -187,7 +175,7 @@
<dependency>
<groupId>com.ticxo.playeranimator</groupId>
<artifactId>PlayerAnimator</artifactId>
<version>R1.2.4</version>
<version>R1.2.5</version>
</dependency>
<!-- Spigot API -->
......
package io.lumine.cosmetics.menus;
import io.lumine.cosmetics.api.cosmetics.Cosmetic;
import io.lumine.cosmetics.managers.MCCosmeticsManager;
import io.lumine.cosmetics.players.Profile;
import io.lumine.utils.serialize.Chroma;
import lombok.Data;
@Data
public class SelectColorContext {
private final Profile profile;
private final MCCosmeticsManager manager;
private final Cosmetic cosmetic;
private Chroma chroma;
}
package io.lumine.cosmetics.menus;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.players.Profile;
import io.lumine.utils.config.properties.types.MenuProp;
import io.lumine.utils.menu.EditableMenuBuilder;
import io.lumine.utils.menu.Icon;
import io.lumine.utils.menu.MenuData;
public class SelectColorMenu extends CosmeticMenu<SelectColorContext> {
public SelectColorMenu(MCCosmeticsPlugin core, MenuManager manager, String type) {
super(core, manager, new MenuProp(core, "menus/color_picker", "Menu", null));
}
@Override
public EditableMenuBuilder<SelectColorContext> build(EditableMenuBuilder<SelectColorContext> builder) {
return builder;
}
public static class ColorSwatch implements MenuData<SelectColorContext> {
@Override
public Icon<SelectColorContext> getIcon() {
// TODO Auto-generated method stub
return null;
}
}
}
......@@ -12,7 +12,7 @@ softdepend:
- PlaceholderAPI
- WorldGuard
loadbefore: []
description: The total solution for all things mob-related.
description: Plugin for adding amazing cosmetics, brought to you by MCModels
commands:
mccosmetics:
description: MCCosmetics admin command
......
......@@ -13,7 +13,7 @@
</organization>
<properties>
<mccosmetics.version>0.10.0</mccosmetics.version>
<mccosmetics.version>0.11.0</mccosmetics.version>
<paperapi.version>1.19-R0.1-SNAPSHOT</paperapi.version>
<lumineutils.version>1.19-SNAPSHOT</lumineutils.version>
<lombok.version>1.18.22</lombok.version>
......@@ -36,6 +36,7 @@
<module>v1_18_R2</module>
<module>v1_19_R1</module>
<module>v1_19_R1_2</module>
<module>v1_19_R2</module>
<module>dist</module>
<module>dist-premium</module>
</modules>
......@@ -91,10 +92,6 @@
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>nexus</id>
<url>https://mvn.lumine.io/repository/maven-private/</url>
</repository>
<!-- <repository>
<id>bstats-repo</id>
<url>http://repo.bstats.org/content/repositories/releases/</url>
......@@ -107,10 +104,6 @@
<updatePolicy>never</updatePolicy>
</releases>
</repository> -->
<repository>
<id>sk89q-repo</id>
<url>https://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>md_5-snapshots</id>
<url>https://repo.md-5.net/content/repositories/snapshots/</url>
......@@ -119,10 +112,6 @@
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>filoghost-repo</id>
<url>https://ci.filoghost.me/plugin/repository/everything/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
......
......@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>MCCosmetics-SQL</artifactId>
<parent>
<parent>
<groupId>io.lumine</groupId>
<artifactId>MCCosmetics-Plugin</artifactId>
<version>${mccosmetics.version}</version>
......@@ -16,6 +16,12 @@
</pluginRepositories>
<dependencies>
<dependency>
<groupId>io.lumine</groupId>
<artifactId>MCCosmetics-API</artifactId>
<version>${mccosmetics.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
......@@ -90,7 +96,7 @@
<jdbc>
<driver>org.mariadb.jdbc.Driver</driver>
<url>jdbc:mariadb://localhost:3306/mythiccraft_test_mccosmetics</url>
<url>jdbc:mariadb://localhost:3306/mythiccraft_test_achievements</url>
<user>mythiccraft_tester</user>
<password>62e06d5e-6c48-4c40-a070-00949d2a9c6a</password>
</jdbc>
......@@ -102,13 +108,13 @@
<excludes></excludes>
<schemata>
<schema>
<inputSchema>mythiccraft_test_mccosmetics</inputSchema>
<inputSchema>mythiccraft_test_achievements</inputSchema>
<outputSchemaToDefault>true</outputSchemaToDefault>
</schema>
</schemata>
</database>
<target>
<packageName>io.lumine.cosmetics.storage.sql.mappings</packageName>
<packageName>io.lumine.achievements.storage.sql.jooq</packageName>
<directory>../plugin/src/main/java</directory>
</target>
</generator>
......
......@@ -77,22 +77,10 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>nexus</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven-private/</url>
</repository>
<repository>
<id>lumine-snapshots</id>
<url>https://mvn.lumine.io/repository/maven-snapshots/</url>
</repository>
<repository>
<id>lumine-test</id>
<url>https://mvn.lumine.io/repository/maven-test/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>minecraft-libraries</id>
<name>Minecraft Libraries</name>
......
......@@ -77,22 +77,10 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>nexus</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven-private/</url>
</repository>
<repository>
<id>lumine-snapshots</id>
<url>https://mvn.lumine.io/repository/maven-snapshots/</url>
</repository>
<repository>
<id>lumine-test</id>
<url>https://mvn.lumine.io/repository/maven-test/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>paper-repo</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
......
......@@ -74,21 +74,9 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>nexus</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven-private/</url>
</repository>
<repository>
<id>lumine-snapshots</id>
<url>https://mvn.lumine.io/repository/maven-snapshots/</url>
</repository>
<repository>
<id>lumine-test</id>
<url>https://mvn.lumine.io/repository/maven-test/</url>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>paper-repo</id>
......
......@@ -74,21 +74,9 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>nexus</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven-private/</url>
</repository>
<repository>
<id>lumine-snapshots</id>
<url>https://mvn.lumine.io/repository/maven-snapshots/</url>
</repository>
<repository>
<id>lumine-test</id>
<url>https://mvn.lumine.io/repository/maven-test/</url>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>paper-repo</id>
......
......@@ -74,21 +74,9 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>nexus</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven-private/</url>
</repository>
<repository>
<id>lumine-snapshots</id>
<url>https://mvn.lumine.io/repository/maven-snapshots/</url>
</repository>
<repository>
<id>lumine-test</id>
<url>https://mvn.lumine.io/repository/maven-test/</url>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>paper-repo</id>
......
/.flattened-pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>MCCosmetics-v1_19_R2</artifactId>
<parent>
<groupId>io.lumine</groupId>
<artifactId>MCCosmetics-Plugin</artifactId>
<version>${mccosmetics.version}</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>1.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile>
<srgIn>org.spigotmc:minecraft-server:1.19.3-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:1.19.3-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<updatePomFile>true</updatePomFile>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>package</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>lumine</id>
<url>https://mvn.lumine.io/repository/maven/</url>
</repository>
<repository>
<id>paper-repo</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>minecraft-libraries</id>
<name>Minecraft Libraries</name>
<url>https://libraries.minecraft.net</url>
</repository>
</repositories>
<dependencies>
<!-- Modules -->
<dependency>
<groupId>io.lumine</groupId>
<artifactId>LumineUtils</artifactId>
<version>${lumineutils.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.lumine</groupId>
<artifactId>MCCosmetics</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- Spigot API -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.19.3-R0.1-SNAPSHOT</version>
<classifier>shaded</classifier>
<scope>provided</scope>
</dependency>
<!-- Spigot NMS version -->
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.19.3-R0.1-SNAPSHOT</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>3.11.50</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>datafixerupper</artifactId>
<version>1.0.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.68.Final</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.8.0-beta4</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package io.lumine.cosmetics.nms;
import com.google.common.collect.Maps;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.Cosmetic;
import io.lumine.cosmetics.api.players.wardrobe.Mannequin;
import io.lumine.cosmetics.api.players.wardrobe.WardrobeTracker;
import io.lumine.cosmetics.managers.back.BackAccessory;
import io.lumine.cosmetics.managers.gestures.Gesture;
import io.lumine.cosmetics.managers.hats.Hat;
import io.lumine.cosmetics.managers.offhand.Offhand;
import io.lumine.cosmetics.managers.sprays.Spray;
import io.lumine.cosmetics.nms.cosmetic.VolatileCosmeticHelper;
import io.lumine.cosmetics.nms.v1_19_R2.cosmetic.*;
import io.lumine.cosmetics.nms.v1_19_R2.network.VolatileChannelHandler;
import io.lumine.cosmetics.nms.v1_19_R2.wardrobe.MannequinEntity;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;
import lombok.Getter;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.entity.LevelEntityGetter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftLivingEntity;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
public class VolatileCodeEnabled_v1_19_R2 implements VolatileCodeHandler {
@Getter private final MCCosmeticsPlugin plugin;
private final Map<Class<? extends Cosmetic>, VolatileCosmeticHelper> cosmeticHelpers = Maps.newConcurrentMap();
private Method entityGetter;
public VolatileCodeEnabled_v1_19_R2(MCCosmeticsPlugin plugin) {
this.plugin = plugin;
cosmeticHelpers.put(Hat.class, new VolatileHatImpl(plugin, this));
cosmeticHelpers.put(BackAccessory.class, new VolatileBackImpl(plugin, this));
cosmeticHelpers.put(Spray.class, new VolatileSprayImpl(plugin, this));
cosmeticHelpers.put(Offhand.class, new VolatileOffhandImpl(plugin, this));
cosmeticHelpers.put(Gesture.class, new VolatileGestureImpl(plugin, this));
for(var method : ServerLevel.class.getMethods()) {
if(LevelEntityGetter.class.isAssignableFrom(method.getReturnType()) && method.getReturnType() != LevelEntityGetter.class) {
entityGetter = method;
break;
}
}
}
@Override
public VolatileCosmeticHelper getCosmeticHelper(Class<? extends Cosmetic> tClass) {
return cosmeticHelpers.get(tClass);
}
@Override
public Collection<VolatileCosmeticHelper> getCosmeticHelpers() {
return cosmeticHelpers.values();
}
@Override
public void injectPlayer(Player player) {
ServerPlayer ply = ((CraftPlayer) player).getHandle();
VolatileChannelHandler cdh = new VolatileChannelHandler(player, this);
ChannelPipeline pipeline = ply.connection.getConnection().channel.pipeline();
for (String name : pipeline.toMap().keySet()) {
if (pipeline.get(name) instanceof Connection) {
pipeline.addBefore(name, "mc_cosmetics_packet_handler", cdh);
break;
}
}
}
@Override
public void removePlayer(Player player) {
Channel channel = ((CraftPlayer) player).getHandle().connection.getConnection().channel;
channel.eventLoop().submit(() -> {
channel.pipeline().remove("mc_cosmetics_packet_handler");
return null;
});
}
public void broadcast(Packet<?>... packets) {
for(Player player : Bukkit.getOnlinePlayers()) {
var connection = ((CraftPlayer) player).getHandle().connection;
for(Packet<?> packet : packets) {
connection.send(packet);
}
}
}
public void broadcast(Player player, Packet<?>... packets) {
var connection = ((CraftPlayer) player).getHandle().connection;
for(Packet<?> packet : packets) {
connection.send(packet);
}
}
public void broadcastAroundAndSelf(Player wearer, Packet<?>... packets) {
final var level = ((CraftWorld) wearer.getWorld()).getHandle();
final var trackedEntity = level.getChunkSource().chunkMap.entityMap.get(wearer.getEntityId());
if(trackedEntity == null) {
broadcast(wearer.getWorld(), packets);
return;
}
for(Packet<?> packet : packets)
trackedEntity.broadcastAndSend(packet);
}
public void broadcastAround(Player wearer, Packet<?>... packets) {
final var level = ((CraftWorld) wearer.getWorld()).getHandle();
final var trackedEntity = level.getChunkSource().chunkMap.entityMap.get(wearer.getEntityId());
if(trackedEntity == null) {
broadcast(wearer.getWorld(), packets);
return;
}
for(Packet<?> packet : packets)
trackedEntity.broadcast(packet);
}
public void broadcast(World world, Packet<?>... packets) {
for(Player player : world.getPlayers()) {
var connection = ((CraftPlayer) player).getHandle().connection;
for(Packet<?> packet : packets) {
connection.send(packet);
}
}
}
public Entity getEntity(World world, int id) {
ServerLevel level = ((CraftWorld) world).getHandle();
try {
var getter = entityGetter != null ?
(LevelEntityGetter<net.minecraft.world.entity.Entity>) entityGetter.invoke(level) :
level.entityManager.getEntityGetter();
final var entity = getter.get(id);
return entity == null ? null : entity.getBukkitEntity();
} catch(Exception | Error ex) {
ex.printStackTrace();
return null;
}
}
@Override
public Mannequin createMannequin(WardrobeTracker tracker, Player player, Location location) {
return new MannequinEntity(tracker,this,player,location);
}
@Override
public void removeFakeEntity(int id) {
ClientboundRemoveEntitiesPacket packet = new ClientboundRemoveEntitiesPacket(id);
broadcast(packet);
}
@Override
public void setBodyYaw(LivingEntity entity, double yaw) {
((CraftLivingEntity) entity).getHandle().yBodyRot = (float) yaw;
}
@Override
public float getBodyYaw(LivingEntity entity) {
return ((CraftLivingEntity) entity).getHandle().yBodyRot;
}
}
package io.lumine.cosmetics.nms.v1_19_R2.cosmetic;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Pair;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.Cosmetic;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.cosmetics.ItemCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.api.players.wardrobe.Mannequin;
import io.lumine.cosmetics.constants.CosmeticType;
import io.lumine.cosmetics.logging.MCLogger;
import io.lumine.cosmetics.managers.back.BackAccessory;
import io.lumine.cosmetics.managers.offhand.Offhand;
import io.lumine.cosmetics.nms.VolatileCodeEnabled_v1_19_R2;
import io.lumine.cosmetics.nms.cosmetic.VolatileEquipmentHelper;
import io.lumine.cosmetics.nms.v1_19_R2.wardrobe.MannequinEntity;
import io.lumine.cosmetics.players.Profile;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class VolatileBackImpl implements VolatileEquipmentHelper {
@Getter
private final MCCosmeticsPlugin plugin;
private final VolatileCodeEnabled_v1_19_R2 nmsHandler;
private final Map<Player, ArmorStand> activeProfile = Maps.newConcurrentMap();
private final Map<Integer, Player> playerTracker = Maps.newConcurrentMap();
public VolatileBackImpl(MCCosmeticsPlugin plugin, VolatileCodeEnabled_v1_19_R2 nmsHandler) {
this.plugin = plugin;
this.nmsHandler = nmsHandler;
}
@Override
public void apply(CosmeticProfile profile) {
if (profile == null)
return;
Player player = profile.getPlayer();
var maybeEquipped = profile.getEquipped(BackAccessory.class);
if(maybeEquipped.isEmpty()) {
return;
}
var equipped = maybeEquipped.get();
var cosmetic = equipped.getCosmetic();
if (!(cosmetic instanceof ItemCosmetic back)) {
return;
}
var nmsPlayer = ((CraftPlayer) player).getHandle();
var nmsBack = CraftItemStack.asNMSCopy(back.getCosmetic(equipped));
ArmorStand stand = activeProfile.get(player);
if(stand == null) {
playerTracker.put(player.getEntityId(), player);
stand = new ArmorStand(EntityType.ARMOR_STAND, ((CraftWorld) player.getWorld()).getHandle());
stand.moveTo(nmsPlayer.getX(), nmsPlayer.getY() + nmsPlayer.getPassengersRidingOffset() + stand.getMyRidingOffset(), nmsPlayer.getZ(), nmsPlayer.getYRot(), 0);
stand.setMarker(true);
stand.setInvisible(true);
stand.setSilent(true);
activeProfile.put(player, stand);
var mobPacket = new ClientboundAddEntityPacket(stand);
var dataPacket = new ClientboundSetEntityDataPacket(stand.getId(), stand.getEntityData().getNonDefaultValues());
var passengersPacket = createPassengerPacket(player.getEntityId(), stand.getId());
nmsHandler.broadcastAroundAndSelf(player, mobPacket, dataPacket, passengersPacket);
}
stand.setItemSlot(EquipmentSlot.HEAD, nmsBack);
var equipmentPacket = new ClientboundSetEquipmentPacket(stand.getId(), List.of(Pair.of(EquipmentSlot.HEAD, nmsBack)));
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
}
@Override
public void unapply(CosmeticProfile profile) {
Player player = profile.getPlayer();
ArmorStand stand = activeProfile.remove(player);
if(stand == null)
return;
playerTracker.remove(player.getEntityId());
ClientboundRemoveEntitiesPacket removePacket = new ClientboundRemoveEntitiesPacket(stand.getId());
nmsHandler.broadcastAroundAndSelf(player, removePacket);
}
@Override
public void equipMannequin(Mannequin mannequin, EquippedCosmetic cosmetic) {
if(!(cosmetic.getCosmetic() instanceof BackAccessory back)) {
return;
}
final var entityId = mannequin.getEntityId();
final var player = mannequin.getPlayer();
var nmsBack = CraftItemStack.asNMSCopy(back.getCosmetic(cosmetic));
var mannequinLocation = mannequin.getLocation();
mannequin.removeExtraEntity(BackAccessory.class);
var stand = new ArmorStand(EntityType.ARMOR_STAND, ((CraftWorld) player.getWorld()).getHandle());
stand.moveTo(mannequinLocation.getX(), mannequinLocation.getY() + stand.getMyRidingOffset(), mannequinLocation.getZ(), mannequinLocation.getYaw(), 0);
stand.setMarker(true);
stand.setInvisible(true);
stand.setSilent(true);
mannequin.addExtraEntity(BackAccessory.class, stand.getId());
var mobPacket = new ClientboundAddEntityPacket(stand);
var dataPacket = new ClientboundSetEntityDataPacket(stand.getId(), stand.getEntityData().getNonDefaultValues());
var passengersPacket = createPassengerPacket(entityId, stand.getId());
nmsHandler.broadcast(player, mobPacket, dataPacket, passengersPacket);
stand.setItemSlot(EquipmentSlot.HEAD, nmsBack);
var equipmentPacket = new ClientboundSetEquipmentPacket(stand.getId(), List.of(Pair.of(EquipmentSlot.HEAD, nmsBack)));
nmsHandler.broadcast(player, equipmentPacket);
}
@Override
public void unequipMannequin(Mannequin mannequin) {
mannequin.removeExtraEntity(BackAccessory.class);
}
@Override
public boolean read(Player sender, Object packet, boolean isCanceled) {
final var profile = MCCosmeticsPlugin.inst().getProfiles().getProfile(sender);
if(profile == null || profile.isHidden(BackAccessory.class))
return true;
if(packet instanceof ServerboundMovePlayerPacket) {
handleRotate(profile);
}else if(packet instanceof ServerboundAcceptTeleportationPacket) {
final var list = handleSpawn(profile);
if(list == null)
return true;
final var connection = ((CraftPlayer) sender).getHandle().connection;
for(Object obj : list) {
connection.send((Packet<?>) obj);
}
}
return true;
}
@Override
public List<Object> write(Player receiver, Object packet) {
if(packet instanceof ClientboundAddPlayerPacket playerPacket) {
int id = playerPacket.getEntityId();
if(playerTracker.containsKey(id)) {
final var spawnedPlayer = playerTracker.get(id);
final var profile = MCCosmeticsPlugin.inst().getProfiles().getProfile(spawnedPlayer);
if(profile == null || profile.isHidden(BackAccessory.class))
return null;
return handleSpawn(profile);
}
}else if(packet instanceof ClientboundRemoveEntitiesPacket removePacket) {
for(int id : removePacket.getEntityIds()) {
if(playerTracker.containsKey(id)) {
return handleDespawn(playerTracker.get(id));
}
}
}
/*
else if(packet instanceof ClientboundMoveEntityPacket moveEntityPacket) {
FriendlyByteBuf byteBuf = new FriendlyByteBuf(Unpooled.buffer());
moveEntityPacket.write(byteBuf);
int id = byteBuf.readVarInt();
if(playerTracker.containsKey(id)) {
final var spawnedPlayer = playerTracker.get(id);
final var profile = MCCosmeticsPlugin.inst().getProfiles().getProfile(spawnedPlayer);
if(profile == null || profile.isHidden(BackAccessory.class))
return null;
return handleMove(profile, moveEntityPacket);
}
}else if(packet instanceof ClientboundTeleportEntityPacket teleportEntityPacket) {
int id = teleportEntityPacket.getId();
if(playerTracker.containsKey(id)) {
final var spawnedPlayer = playerTracker.get(id);
final var profile = MCCosmeticsPlugin.inst().getProfiles().getProfile(spawnedPlayer);
if(profile == null || profile.isHidden(BackAccessory.class))
return null;
return handleTeleport(profile);
}
}*/
return null;
}
private void handleRotate(Profile profile) {
if(!hasBack(profile))
return;
final var wearer = profile.getPlayer();
final var nmsPlayer = ((CraftPlayer) wearer).getHandle();
final var stand = activeProfile.get(wearer);
ClientboundRotateHeadPacket packet = new ClientboundRotateHeadPacket(stand, VolatileEquipmentHelper.toByte(nmsPlayer.getYRot()));
nmsHandler.broadcastAroundAndSelf(wearer, packet);
}
private List<Object> handleSpawn(Profile profile) {
if(!hasBack(profile))
return null;
final var wearer = profile.getPlayer();
final var stand = activeProfile.get(wearer);
var mobPacket = new ClientboundAddEntityPacket(stand);
ClientboundSetEntityDataPacket dataPacket = new ClientboundSetEntityDataPacket(stand.getId(), stand.getEntityData().getNonDefaultValues());
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(stand.getId(), List.of(Pair.of(EquipmentSlot.HEAD, stand.getItemBySlot(EquipmentSlot.HEAD))));
ClientboundSetPassengersPacket passengersPacket = createPassengerPacket(wearer.getEntityId(), stand.getId());
return List.of(mobPacket, dataPacket, equipmentPacket, passengersPacket);
}
private List<Object> handleDespawn(Player player) {
final var stand = activeProfile.get(player);
if(stand == null)
return null;
ClientboundRemoveEntitiesPacket removePacket = new ClientboundRemoveEntitiesPacket(stand.getId());
return List.of(removePacket);
}
private List<Object> handleMove(Profile profile, ClientboundMoveEntityPacket moveEntityPacket) {
if(!hasBack(profile))
return null;
final var wearer = profile.getPlayer();
final var stand = activeProfile.get(wearer);
ClientboundMoveEntityPacket move;
if(moveEntityPacket.hasPosition() && moveEntityPacket.hasRotation()) {
move = new ClientboundMoveEntityPacket.PosRot(
stand.getId(),
moveEntityPacket.getXa(),
moveEntityPacket.getYa(),
moveEntityPacket.getZa(),
moveEntityPacket.getyRot(),
moveEntityPacket.getxRot(),
false);
}else if(moveEntityPacket.hasPosition()) {
move = new ClientboundMoveEntityPacket.Pos(
stand.getId(),
moveEntityPacket.getXa(),
moveEntityPacket.getYa(),
moveEntityPacket.getZa(),
false);
}else {
move = new ClientboundMoveEntityPacket.Rot(
stand.getId(),
moveEntityPacket.getyRot(),
moveEntityPacket.getxRot(),
false);
}
return List.of(move);
}
private List<Object> handleTeleport(Profile profile) {
if(!hasBack(profile))
return null;
final var wearer = profile.getPlayer();
final var nmsPlayer = ((CraftPlayer) wearer).getHandle();
final var stand = activeProfile.get(wearer);
stand.moveTo(nmsPlayer.getX(), nmsPlayer.getY() + nmsPlayer.getPassengersRidingOffset() + stand.getMyRidingOffset(), nmsPlayer.getZ(), nmsPlayer.getYRot(), 0);
return List.of(new ClientboundTeleportEntityPacket(stand));
}
private boolean hasBack(Profile profile) {
if(profile == null)
return false;
var maybeBack = profile.getEquipped(BackAccessory.class);
return maybeBack.isPresent() && maybeBack.get().getCosmetic() instanceof ItemCosmetic && activeProfile.containsKey(profile.getPlayer());
}
private ClientboundSetPassengersPacket createPassengerPacket(int mount, int... driver) {
FriendlyByteBuf bb = new FriendlyByteBuf(Unpooled.buffer());
bb.writeVarInt(mount);
bb.writeVarIntArray(driver);
return new ClientboundSetPassengersPacket(bb);
}
}
\ No newline at end of file
package io.lumine.cosmetics.nms.v1_19_R2.cosmetic;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.mojang.datafixers.util.Pair;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.manager.HideableCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.managers.gestures.Gesture;
import io.lumine.cosmetics.managers.gestures.GestureManager;
import io.lumine.cosmetics.managers.gestures.QuitMethod;
import io.lumine.cosmetics.nms.VolatileCodeEnabled_v1_19_R2;
import io.lumine.cosmetics.nms.cosmetic.VolatileEquipmentHelper;
import io.lumine.cosmetics.players.Profile;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.game.*;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.horse.Horse;
import net.minecraft.world.item.ItemStack;
import org.bukkit.attribute.Attribute;
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R2.attribute.CraftAttributeMap;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class VolatileGestureImpl implements VolatileEquipmentHelper {
private static final List<Pair<EquipmentSlot, ItemStack>> empty = new ArrayList<>();
static {
for(final var slot : EquipmentSlot.values())
empty.add(Pair.of(slot, ItemStack.EMPTY));
}
@Getter
private final MCCosmeticsPlugin plugin;
private final VolatileCodeEnabled_v1_19_R2 nmsHandler;
private final Set<Player> activeProfile = Sets.newConcurrentHashSet();
private final Map<Integer, Player> playerTracker = Maps.newConcurrentMap();
private Horse horse;
public VolatileGestureImpl(MCCosmeticsPlugin plugin, VolatileCodeEnabled_v1_19_R2 nmsHandler) {
this.plugin = plugin;
this.nmsHandler = nmsHandler;
}
@Override
public void apply(CosmeticProfile profile) {
if (profile == null)
return;
Player player = profile.getPlayer();
if(activeProfile.contains(player))
return;
final var maybeEquipped = profile.getEquipped(Gesture.class);
if(maybeEquipped.isEmpty()) {
return;
}
var opt = maybeEquipped.get().getCosmetic();
if(!(opt instanceof Gesture gesture))
return;
playerTracker.put(player.getEntityId(), player);
activeProfile.add(player);
if(!gesture.isCanMove())
getHorsed(player);
player.setInvisible(true);
for(final var value : ((Profile) profile).getEquipped().values()) {
final var manager = value.getCosmetic().getManager();
if(!(manager instanceof HideableCosmetic hide))
continue;
hide.hide(profile, gesture);
}
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), empty);
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
}
@Override
public void unapply(CosmeticProfile profile) {
if (profile == null)
return;
Player player = profile.getPlayer();
if(!activeProfile.contains(player))
return;
activeProfile.remove(player);
playerTracker.remove(player.getEntityId());
nmsHandler.broadcast(player, new ClientboundRemoveEntitiesPacket(horse.getId()));
final var nmsPlayer = ((CraftPlayer) player).getHandle();
List<Pair<EquipmentSlot, ItemStack>> equipment = new ArrayList<>();
for(EquipmentSlot slot : EquipmentSlot.values())
equipment.add(Pair.of(slot, nmsPlayer.getItemBySlot(slot)));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), equipment);
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
player.setInvisible(false);
for(final var value : ((Profile) profile).getEquipped().values()) {
final var manager = value.getCosmetic().getManager();
if(!(manager instanceof HideableCosmetic hide))
continue;
hide.show(profile);
}
}
private ClientboundSetPassengersPacket createPassengerPacket(int mount, int... driver) {
FriendlyByteBuf bb = new FriendlyByteBuf(Unpooled.buffer());
bb.writeVarInt(mount);
bb.writeVarIntArray(driver);
return new ClientboundSetPassengersPacket(bb);
}
private void getHorsed(Player player) {
final var nmsPlayer = ((CraftPlayer) player).getHandle();
if(horse == null) {
horse = new Horse(EntityType.HORSE, ((CraftWorld) player.getWorld()).getHandle());
horse.setInvisible(true);
horse.setHealth(0);
horse.getAttribute(CraftAttributeMap.toMinecraft(Attribute.GENERIC_MAX_HEALTH)).setBaseValue(0);
}
horse.setPos(nmsPlayer.getX(), nmsPlayer.getY() - horse.getPassengersRidingOffset() - nmsPlayer.getMyRidingOffset(), nmsPlayer.getZ());
var mobPacket = new ClientboundAddEntityPacket(horse);
var dataPacket = new ClientboundSetEntityDataPacket(horse.getId(), horse.getEntityData().getNonDefaultValues());
var attributesPacket = new ClientboundUpdateAttributesPacket(horse.getId(), horse.getAttributes().getSyncableAttributes());
var passengersPacket = createPassengerPacket(horse.getId(), nmsPlayer.getId());
nmsHandler.broadcast(player, mobPacket, dataPacket, attributesPacket, passengersPacket);
}
@Override
public boolean read(Player sender, Object packet, boolean isCanceled) {
if(!plugin.getGestureManager().getTicking().containsKey(sender)) {
return true;
}
if(packet instanceof ServerboundPlayerInputPacket inputPacket) {
final var manager = (GestureManager) plugin.getGestureManager();
if(inputPacket.isShiftKeyDown())
manager.quit(sender, QuitMethod.SNEAK);
if(inputPacket.isJumping())
manager.quit(sender, QuitMethod.JUMP);
}else if(packet instanceof ServerboundSetCarriedItemPacket setSlotPacket) {
int oSlot = sender.getInventory().getHeldItemSlot();
if(oSlot != setSlotPacket.getSlot()) {
nmsHandler.broadcast(sender, new ClientboundSetCarriedItemPacket(oSlot));
return false;
}
}
return true;
}
@Override
public List<Object> write(Player receiver, Object packet) {
if(packet instanceof ClientboundSetEquipmentPacket equipmentPacket) {
int id = equipmentPacket.getEntity();
final var spawnedPlayer = playerTracker.get(id);
if(spawnedPlayer == null)
return null;
final var profile = MCCosmeticsPlugin.inst().getProfiles().getProfile(spawnedPlayer);
if(profile != null)
return List.of(new ClientboundSetEquipmentPacket(id, empty));
}
return null;
}
}
package io.lumine.cosmetics.nms.v1_19_R2.cosmetic;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Pair;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.cosmetics.ItemCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.api.players.wardrobe.Mannequin;
import io.lumine.cosmetics.managers.hats.Hat;
import io.lumine.cosmetics.nms.VolatileCodeEnabled_v1_19_R2;
import io.lumine.cosmetics.nms.cosmetic.VolatileEquipmentHelper;
import io.lumine.cosmetics.players.Profile;
import io.lumine.utils.logging.Log;
import io.lumine.utils.reflection.Reflector;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.game.ClientboundAddPlayerPacket;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket;
import net.minecraft.world.entity.EquipmentSlot;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class VolatileHatImpl implements VolatileEquipmentHelper {
@Getter private final MCCosmeticsPlugin plugin;
private final VolatileCodeEnabled_v1_19_R2 nmsHandler;
//private final Map<Integer, Player> playerTracker = Maps.newConcurrentMap();
public VolatileHatImpl(MCCosmeticsPlugin plugin, VolatileCodeEnabled_v1_19_R2 nmsHandler) {
this.plugin = plugin;
this.nmsHandler = nmsHandler;
}
@Override
public void apply(CosmeticProfile profile) {
if (profile == null)
return;
Player player = profile.getPlayer();
final var maybeEquipped = profile.getEquipped(Hat.class);
if(maybeEquipped.isEmpty()) {
return;
}
var opt = maybeEquipped.get().getCosmetic();
if(!(opt instanceof Hat hat))
return;
var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(maybeEquipped.get()));
//playerTracker.put(player.getEntityId(), player);
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.HEAD, nmsHat)));
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
}
@Override
public void unapply(CosmeticProfile profile) {
final var nmsPlayer = ((CraftPlayer) profile.getPlayer()).getHandle();
final var item = nmsPlayer.getItemBySlot(EquipmentSlot.HEAD);
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(nmsPlayer.getId(), List.of(Pair.of(EquipmentSlot.HEAD, item)));
nmsHandler.broadcastAroundAndSelf(nmsPlayer.getBukkitEntity(), equipmentPacket);
}
@Override
public void equipMannequin(Mannequin mannequin, EquippedCosmetic cosmetic) {
if(!(cosmetic.getCosmetic() instanceof Hat hat)) {
return;
}
final var entityId = mannequin.getEntityId();
final var player = mannequin.getPlayer();
var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(cosmetic));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(entityId,
List.of(Pair.of(EquipmentSlot.HEAD, nmsHat)));
nmsHandler.broadcast(player, equipmentPacket);
}
@Override
public void unequipMannequin(Mannequin mannequin) {
final var nmsPlayer = ((CraftPlayer) mannequin.getPlayer()).getHandle();
final var item = nmsPlayer.getItemBySlot(EquipmentSlot.HEAD);
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(nmsPlayer.getId(), List.of(Pair.of(EquipmentSlot.HEAD, item)));
nmsHandler.broadcast(nmsPlayer.getBukkitEntity(), equipmentPacket);
}
@Override
public boolean read(Player sender, Object packet, boolean isCanceled) {
if(packet instanceof ServerboundAcceptTeleportationPacket) {
final var profile = MCCosmeticsPlugin.inst().getProfiles().getProfile(sender);
if(profile == null || profile.isHidden(Hat.class))
return true;
handleSpawn(profile);
}
return true;
}
@Override
public List<Object> write(Player receiver, Object packet) {
/*
if(packet instanceof ClientboundAddPlayerPacket playerPacket) {
int id = playerPacket.getEntityId();
Profile profile = getProfile(receiver, id);
if(profile != null && !profile.isHidden(Hat.class)) {
handleSpawn(profile);
}
} else */
if(packet instanceof ClientboundSetEquipmentPacket equipmentPacket) {
int id = equipmentPacket.getEntity();
Profile profile = getProfile(receiver, id);
if(profile != null && !profile.isHidden(Hat.class)) {
modifyPacket(profile, equipmentPacket);
}
}
return null;
}
private Profile getProfile(Player receiver, int id) {
final var entity = nmsHandler.getEntity(receiver.getWorld(), id);
if(!(entity instanceof Player player))
return null;
return plugin.getProfiles().getProfile(player);
}
public void handleSpawn(Profile profile) {
final var maybeEquipped = profile.getEquipped(Hat.class);
if(maybeEquipped.isEmpty()) {
return;
}
var equip = maybeEquipped.get();
var opt = equip.getCosmetic();
if(!(opt instanceof ItemCosmetic hat)) {
return;
}
final var player = profile.getPlayer();
final var nmsHat = CraftItemStack.asNMSCopy(hat.getCosmetic(equip));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.HEAD, nmsHat)));
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
}
private static Reflector<ClientboundSetEquipmentPacket> refEq = new Reflector(ClientboundSetEquipmentPacket.class, "c");
private void modifyPacket(Profile profile, ClientboundSetEquipmentPacket packet) {
final var maybeEquipped = profile.getEquipped(Hat.class);
if(maybeEquipped.isEmpty()) {
return;
}
var equip = maybeEquipped.get();
var opt = equip.getCosmetic();
if(!(opt instanceof ItemCosmetic hat)) {
return;
}
final var nmsItem = CraftItemStack.asNMSCopy(hat.getCosmetic(equip));
var slots = (List<Pair<EquipmentSlot,net.minecraft.world.item.ItemStack>>) packet.getSlots();
List<Pair<EquipmentSlot,net.minecraft.world.item.ItemStack>> newSlots = new ArrayList<>();
boolean foundHead = false;
for(var pair : slots) {
final EquipmentSlot slot = pair.getFirst();
if(slot == EquipmentSlot.HEAD) {
foundHead = true;
newSlots.add(Pair.of(pair.getFirst(), nmsItem));
} else {
newSlots.add(pair);
}
}
if(!foundHead) {
newSlots.add(Pair.of(EquipmentSlot.HEAD, nmsItem));
}
refEq.set(packet, "c", newSlots);
}
}
package io.lumine.cosmetics.nms.v1_19_R2.cosmetic;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Pair;
import io.lumine.cosmetics.MCCosmeticsPlugin;
import io.lumine.cosmetics.api.cosmetics.EquippedCosmetic;
import io.lumine.cosmetics.api.cosmetics.ItemCosmetic;
import io.lumine.cosmetics.api.players.CosmeticProfile;
import io.lumine.cosmetics.api.players.wardrobe.Mannequin;
import io.lumine.cosmetics.managers.hats.Hat;
import io.lumine.cosmetics.managers.offhand.Offhand;
import io.lumine.cosmetics.nms.VolatileCodeEnabled_v1_19_R2;
import io.lumine.cosmetics.nms.cosmetic.VolatileEquipmentHelper;
import io.lumine.cosmetics.players.Profile;
import io.lumine.utils.reflection.Reflector;
import io.netty.buffer.Unpooled;
import lombok.Getter;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.game.ClientboundAddPlayerPacket;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
import net.minecraft.world.entity.EquipmentSlot;
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class VolatileOffhandImpl implements VolatileEquipmentHelper {
@Getter private final MCCosmeticsPlugin plugin;
private final VolatileCodeEnabled_v1_19_R2 nmsHandler;
private final Map<Integer, Player> playerTracker = Maps.newConcurrentMap();
public VolatileOffhandImpl(MCCosmeticsPlugin plugin, VolatileCodeEnabled_v1_19_R2 nmsHandler) {
this.plugin = plugin;
this.nmsHandler = nmsHandler;
}
@Override
public void apply(CosmeticProfile profile) {
if (profile == null)
return;
Player player = profile.getPlayer();
final var maybeEquipped = profile.getEquipped(Offhand.class);
if(maybeEquipped.isEmpty()) {
return;
}
var equip = maybeEquipped.get();
var opt = equip.getCosmetic();
if(!(opt instanceof ItemCosmetic offhand))
return;
var nmsOffhand = CraftItemStack.asNMSCopy(offhand.getCosmetic(equip));
playerTracker.put(player.getEntityId(), player);
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.OFFHAND, nmsOffhand)));
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
}
@Override
public void unapply(CosmeticProfile profile) {
final var nmsPlayer = ((CraftPlayer) profile.getPlayer()).getHandle();
final var item = nmsPlayer.getItemBySlot(EquipmentSlot.OFFHAND);
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(nmsPlayer.getId(), List.of(Pair.of(EquipmentSlot.OFFHAND, item)));
nmsHandler.broadcastAroundAndSelf(nmsPlayer.getBukkitEntity(), equipmentPacket);
}
@Override
public void equipMannequin(Mannequin mannequin, EquippedCosmetic cosmetic) {
if(!(cosmetic.getCosmetic() instanceof Offhand offhand)) {
return;
}
final var entityId = mannequin.getEntityId();
final var player = mannequin.getPlayer();
var nmsHat = CraftItemStack.asNMSCopy(offhand.getCosmetic(cosmetic));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(entityId, List.of(Pair.of(EquipmentSlot.OFFHAND, nmsHat)));
nmsHandler.broadcast(player, equipmentPacket);
}
@Override
public void unequipMannequin(Mannequin mannequin) {
final var nmsPlayer = ((CraftPlayer) mannequin.getPlayer()).getHandle();
final var item = nmsPlayer.getItemBySlot(EquipmentSlot.OFFHAND);
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(nmsPlayer.getId(), List.of(Pair.of(EquipmentSlot.OFFHAND, item)));
nmsHandler.broadcast(nmsPlayer.getBukkitEntity(), equipmentPacket);
}
@Override
public List<Object> write(Player receiver, Object packet) {
if(packet instanceof ClientboundSetEquipmentPacket equipmentPacket) {
int id = equipmentPacket.getEntity();
Profile profile = getProfile(receiver, id);
if(profile != null && !profile.isHidden(Offhand.class))
modifyPacket(profile, equipmentPacket);
}
return null;
}
private Profile getProfile(Player receiver, int id) {
final var entity = nmsHandler.getEntity(receiver.getWorld(), id);
if(!(entity instanceof Player player))
return null;
return plugin.getProfiles().getProfile(player);
}
public void handleSpawn(Profile profile) {
final var maybeEquipped = profile.getEquipped(Offhand.class);
if(maybeEquipped.isEmpty()) {
return;
}
var equip = maybeEquipped.get();
var opt = equip.getCosmetic();
if(!(opt instanceof ItemCosmetic offhand))
return;
final var player = profile.getPlayer();
final var nmsOffhand = CraftItemStack.asNMSCopy(offhand.getCosmetic(equip));
ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(player.getEntityId(), List.of(Pair.of(EquipmentSlot.OFFHAND, nmsOffhand)));
nmsHandler.broadcastAroundAndSelf(player, equipmentPacket);
}
private static Reflector<ClientboundSetEquipmentPacket> refEq = new Reflector(ClientboundSetEquipmentPacket.class, "c");
private void modifyPacket(Profile profile, ClientboundSetEquipmentPacket packet) {
final var maybeEquipped = profile.getEquipped(Hat.class);
if(maybeEquipped.isEmpty()) {
return;
}
var equip = maybeEquipped.get();
var opt = equip.getCosmetic();
if(!(opt instanceof ItemCosmetic hat)) {
return;
}
final var nmsItem = CraftItemStack.asNMSCopy(hat.getCosmetic(equip));
var slots = (List<Pair<EquipmentSlot,net.minecraft.world.item.ItemStack>>) packet.getSlots();
List<Pair<EquipmentSlot,net.minecraft.world.item.ItemStack>> newSlots = new ArrayList<>();
boolean foundHead = false;
for(var pair : slots) {
final EquipmentSlot slot = pair.getFirst();
if(slot == EquipmentSlot.HEAD) {
foundHead = true;
newSlots.add(Pair.of(pair.getFirst(), nmsItem));
} else {
newSlots.add(pair);
}
}
if(!foundHead) {
newSlots.add(Pair.of(EquipmentSlot.HEAD, nmsItem));
}
refEq.set(packet, "c", newSlots);
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment