Skip to content

Instantly share code, notes, and snippets.

@HeathLoganCampbell
Last active January 29, 2024 12:40
Show Gist options
  • Save HeathLoganCampbell/3e5c0a482b509f8d490cd0fb9ebb57e6 to your computer and use it in GitHub Desktop.
Save HeathLoganCampbell/3e5c0a482b509f8d490cd0fb9ebb57e6 to your computer and use it in GitHub Desktop.
Disguise items to players via packet, basically have under the hood item seperate for what each player sees. this means you can customize each item for each viewer
package net.skyblock.realm.customitems;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.WrappedDataValue;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
import com.comphenix.protocol.wrappers.nbt.NbtWrapper;
import com.google.common.collect.Lists;
import de.tr7zw.changeme.nbtapi.NBTItem;
import net.minecraft.server.level.EntityPlayer;
import net.minecraft.server.level.WorldServer;
import net.minecraft.world.entity.projectile.EntityFishingHook;
import org.bukkit.*;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
public class RealmCustomItemsPlugin extends JavaPlugin
{
// Deep sea fishing?
// Net fishing?
// Lava fishing
// spear fishing
private static final WrappedDataWatcher.Serializer serializer = WrappedDataWatcher.Registry.getItemStackSerializer(false);
public static Material UNDER_LAYING_MATERIAL = Material.FISHING_ROD;
public static Material DISPLAY_MATERIAL = Material.FISHING_ROD;
private void replaceItem(ItemStack itemStack)
{
if(itemStack.getType() != UNDER_LAYING_MATERIAL) return;
NbtWrapper<?> wrapper = NbtFactory.fromItemTag(itemStack);
NbtCompound compound = NbtFactory.asCompound(wrapper);
if(!compound.containsKey("custom_item_id")) return;
int customItemId = compound.getInteger("custom_item_id");
if(customItemId == 1)
{
itemStack.setType(DISPLAY_MATERIAL);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setDisplayName(ChatColor.GREEN + "Fishing Rod");
ArrayList<String> lines = new ArrayList<>();
lines.add(CC.gray + "Your run of the mill fishing rod");
lines.add(CC.gray + "used to catch a meal for one.");
lines.add("");
lines.add(CC.bGray + "COMMON");
itemMeta.setLore(lines);
itemStack.setItemMeta(itemMeta);
}
}
private Entity getEntityById(World world, int entityId)
{
for (Entity entity : world.getEntities()) {
if (entity.getEntityId() == entityId) {
return entity;
}
}
return null;
}
private void spawnEntity(Location location, Vector vector, EntityType type, int shooterId) {
int entityId = 10000;
PacketContainer packet = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
packet.getIntegers().write(0, entityId);
packet.getUUIDs().write(0, UUID.randomUUID());
packet.getEntityTypeModifier().write(0, type);
packet.getDoubles()
.write(0, location.getX())
.write(1, location.getY())
.write(2, location.getZ());
packet.getIntegers()
.write(1, convertVelocity(vector.getX()))
.write(2, convertVelocity(vector.getY()))
.write(3, convertVelocity(vector.getZ()))
.write(4, shooterId);
for(Player player : Bukkit.getOnlinePlayers()) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
}
WrappedDataWatcher.Serializer intType = WrappedDataWatcher.Registry.get(Integer.class);
int fishingHookEntityId = 10000;
ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
PacketContainer metadataPacket = protocolManager.createPacket(PacketType.Play.Server.ENTITY_METADATA);
metadataPacket.getIntegers().write(0, fishingHookEntityId);
for(Player player : Bukkit.getOnlinePlayers()) {
int targetEntityId = player.getEntityId(); // The entity ID of the entity to attach the fishing hook to
List<WrappedDataValue> values = Lists.newArrayList(
new WrappedDataValue(0, intType, -1));
metadataPacket.getDataValueCollectionModifier().write(0, values);
protocolManager.sendServerPacket(player, metadataPacket);
}
}
private int convertVelocity(double velocity) {
return (int) (clamp(velocity, -3.9, 3.9) * 8000);
}
public static double clamp(double targetNum, double min, double max) {
// Makes sure a number is within a range
return Math.max(min, Math.min(targetNum, max));
}
// RealmsTextures
// Sea Horse
///https://mcmodels.net/products/9164/more-fish
@Override
public void onEnable() {
// Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);
Bukkit.getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onGameModeChange(PlayerGameModeChangeEvent e)
{
Player player = e.getPlayer();
Bukkit.getScheduler().scheduleSyncDelayedTask(RealmCustomItemsPlugin.this, () -> {
player.updateInventory();
}, 1L);
}
@EventHandler
public void onPaper(PlayerInteractEvent e)
{
if (!e.getAction().equals(Action.RIGHT_CLICK_AIR)) {
return;
}
if(!e.getItem().getType().equals(UNDER_LAYING_MATERIAL))
{
return;
}
NBTItem nbte = new NBTItem(e.getItem());
if (!nbte.hasTag("custom_item_id"))
{
return;
}
Integer customItemId = nbte.getInteger("custom_item_id");
if(customItemId == 1)
{
// Vector vec = e.getPlayer().getLocation().getDirection().multiply(1.5);
// e.getPlayer().launchProjectile(FishHook.class, vec);
}
}
private static int ENTITY_ID = 100000;
@EventHandler
public void onShift(PlayerToggleSneakEvent e)
{
// Location location = e.getPlayer().getLocation();
// spawnEntity(location, new Vector(0, 1, 0), EntityType.FISHING_HOOK, e.getPlayer().getEntityId());
}
@EventHandler
public void onCommand(PlayerCommandPreprocessEvent e)
{
if (e.getMessage().toLowerCase().contains("yeet")) {
int customItemId = 1;
ItemStack itemStack = new ItemStack(UNDER_LAYING_MATERIAL);
ItemMeta itemMeta = itemStack.getItemMeta();
ArrayList<String> lines = new ArrayList<>();
lines.add("Custom Item Id: " + customItemId);
itemMeta.setLore(lines);
itemStack.setItemMeta(itemMeta);
NBTItem nbte = new NBTItem(itemStack);
nbte.setInteger("custom_item_id", customItemId);
ItemStack item = nbte.getItem();
e.getPlayer().getInventory().addItem(item);
}
}
}, this);
ProtocolLibrary.getProtocolManager().addPacketListener(
new PacketAdapter(this, ListenerPriority.NORMAL, PacketType.Play.Server.WINDOW_ITEMS, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS, PacketType.Play.Server.SPAWN_ENTITY, PacketType.Play.Server.ENTITY_METADATA) {
@Override
public void onPacketSending(PacketEvent event) {
PacketContainer packet = event.getPacket();
if(event.getPlayer().getGameMode() == GameMode.CREATIVE) return;
if (event.getPacketType() == PacketType.Play.Server.SET_SLOT)
{
ItemStack itemStack = packet.getItemModifier().read(0);
if (itemStack != null && itemStack.getType() != Material.AIR) {
replaceItem(itemStack);
}
}
if (event.getPacketType() == PacketType.Play.Server.WINDOW_ITEMS) {
List<ItemStack> itemStacks = packet.getItemListModifier().read(0);
ItemStack carrierItem = packet.getItemModifier().read(0);
if (carrierItem != null && carrierItem.getType() != Material.AIR) {
replaceItem(carrierItem);
}
for (ItemStack itemStack: itemStacks) {
if (itemStack != null && itemStack.getType() != Material.AIR) {
replaceItem(itemStack);
}
}
}
if(event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA)
{
int entityId = packet.getIntegers().read(0);
Entity entity = getEntityById(event.getPlayer().getWorld(), entityId);
if (entity instanceof Item) {
Item item = (Item) entity;
ItemStack itemStack = item.getItemStack();
if (itemStack.getType() == UNDER_LAYING_MATERIAL)
{
packet.getDataValueCollectionModifier()
.write(0, List.of(
// https://wiki.vg/Entity_metadata#Item_Entity
new WrappedDataValue(8, serializer, MinecraftReflection.getMinecraftItemStack(new ItemStack(DISPLAY_MATERIAL)))
));
}
}
}
event.setPacket(packet);
}
}
);
}
}
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>dmulloy2-repo</id>
<url>https://repo.dmulloy2.net/repository/public/</url>
</repository>
<repository>
<id>aikar</id>
<url>https://repo.aikar.co/content/groups/aikar/</url>
</repository>
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.20.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>5.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.tr7zw</groupId>
<artifactId>item-nbt-api</artifactId>
<version>2.12.2</version>
</dependency>
</dependencies>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment