14 Commits

Author SHA1 Message Date
Oliver
a2a2d39d7e dev builds for 1.21.11 2025-11-08 13:41:45 +01:00
Oliver
3388ae6d80 fancynpcs: Update version to 2.8.0.307 2025-11-08 13:36:49 +01:00
Oliver
ab5826be3c docs: Add npc rotate command and inverted need_permission 2025-11-08 13:36:33 +01:00
TheosRee
24c1907eec fancynpcs, fancyholograms: Use sets of Version Strings for checking if a version is valid (#142)
* use set for checking if a version is valid

* use Paper PR for snapshot reference

---------

Co-authored-by: TheosRee <theosree@users.noreply.github.com>
2025-11-08 13:30:57 +01:00
Oliver
d36af3cd00 Update gradle plugins 2025-11-08 13:30:57 +01:00
Oliver
bfd39c60b0 Update gradle wrapper to 9.2.0 2025-11-08 13:30:57 +01:00
Oliver
02fa1f0fa6 Remove publishing to hangar and modrinth via gradle plugins 2025-11-08 13:30:57 +01:00
Oliver
1ee7bdcd98 fancynpcs: Update changelog 2025-11-08 13:30:57 +01:00
Oliver
a27fd2e0c4 fancyholograms, fancynpcs: Update changelog 2025-11-08 13:30:57 +01:00
Oliver
d74fd4bab1 fancyholograms v2 & v3, fancydialogs: Add support for 1.21.11 2025-11-08 13:30:57 +01:00
Oliver
7d5b86fd14 packets: Add support for 1.21.11 2025-11-08 13:30:57 +01:00
Oliver
fb2beeb5b2 fancynpcs: Fix version number typos 2025-11-08 13:30:57 +01:00
Oliver
bbd361ea0d fancynpcs: Add support for 1.21.11 2025-11-08 13:30:57 +01:00
Alex
d9333f12f5 fancynpcs: Implemented inversed permission checks -> "!" prefix for perms (#139)
* Implemented feature from here: https://github.com/FancyInnovations/FancyPlugins/issues/86

* Implemented feature from here: https://github.com/FancyInnovations/FancyPlugins/issues/50
2025-11-08 13:14:05 +01:00
100 changed files with 4173 additions and 214 deletions

View File

@@ -1,10 +1,8 @@
plugins { plugins {
id("com.gradleup.shadow") version "9.0.0-beta17" apply false id("com.gradleup.shadow") version "9.2.2" apply false
id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false id("io.papermc.paperweight.userdev") version "2.0.0-beta.19" apply false
id("xyz.jpenilla.run-paper") version "2.3.1" apply false id("xyz.jpenilla.run-paper") version "3.0.2" apply false
id("de.eldoria.plugin-yml.paper") version "0.7.1" apply false id("de.eldoria.plugin-yml.paper") version "0.8.0" apply false
id("io.papermc.hangar-publish-plugin") version "0.1.3" apply false
id("com.modrinth.minotaur") version "2.+" apply false
} }
allprojects { allprojects {
@@ -17,5 +15,12 @@ allprojects {
maven("https://repo.papermc.io/repository/maven-public/") maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.fancyinnovations.com/releases") maven("https://repo.fancyinnovations.com/releases")
maven(url = "https://jitpack.io") maven(url = "https://jitpack.io")
maven("https://maven-prs.papermc.io/Paper/pr13194") {
name = "Maven for PR #13194" // https://github.com/PaperMC/Paper/pull/13194
mavenContent {
includeModule("io.papermc.paper", "dev-bundle")
includeModule("io.papermc.paper", "paper-api")
}
}
} }
} }

View File

@@ -177,6 +177,13 @@ Teleports NPC to specified location.
- **Syntax**: `/npc move_to (npc) (x) (y) (z) [world] [--look-in-my-direction]` - **Syntax**: `/npc move_to (npc) (x) (y) (z) [world] [--look-in-my-direction]`
- **Permissions**: `fancynpcs.command.npc.move_to` - **Permissions**: `fancynpcs.command.npc.move_to`
### Rotate npc
Sets the yaw and pitch of the specified NPC.
- **Syntax**: `/npc rotate (npc) (yaw) (pitch)`
- **Permissions**: `fancynpcs.command.npc.rotate`
### Center npc location ### Center npc location
Centers the NPC to the specified location. Centers the NPC to the specified location.

View File

@@ -122,6 +122,10 @@ Syntax: `need_permission (permission)`
Example: `/npc action (npc) (trigger) add need_permission my.cool.permission` Example: `/npc action (npc) (trigger) add need_permission my.cool.permission`
!!!info
If you add the `!` prefix to the permission, the action will be inverted. This means that the action list will be canceled if the player has the permission.
!!!
### play_sound ### play_sound
Plays a sound to the player. This action is useful for creating audio feedback for the player when interacting with the NPC. Plays a sound to the player. This action is useful for creating audio feedback for the player when interacting with the NPC.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

View File

@@ -21,6 +21,7 @@ dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
implementation(project(":libraries:packets:packets-api")) implementation(project(":libraries:packets:packets-api"))
implementation(project(":libraries:packets:implementations:1_21_11"))
implementation(project(":libraries:packets:implementations:1_21_9")) implementation(project(":libraries:packets:implementations:1_21_9"))
implementation(project(":libraries:packets:implementations:1_21_6")) implementation(project(":libraries:packets:implementations:1_21_6"))
implementation(project(":libraries:packets:implementations:1_21_5")) implementation(project(":libraries:packets:implementations:1_21_5"))

View File

@@ -0,0 +1,23 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION
dependencies {
paperweight.paperDevBundle("25w45a-R0.1-SNAPSHOT")
compileOnly(project(":libraries:packets:packets-api"))
testImplementation(project(":libraries:packets"))
testImplementation(project(":libraries:packets:packets-api"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.12.2")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.12.2")
testImplementation("org.junit.platform:junit-platform-console-standalone:1.12.2")
}
tasks {
test {
useJUnitPlatform()
}
}

View File

@@ -0,0 +1,48 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundAddEntityPacket;
import de.oliver.fancysitula.api.utils.AngelConverter;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.entity.EntityType;
import java.util.UUID;
public class ClientboundAddEntityPacketImpl extends FS_ClientboundAddEntityPacket {
public ClientboundAddEntityPacketImpl(int entityId, UUID entityUUID, EntityType entityType, double x, double y, double z, float yaw, float pitch, float headYaw, int velocityX, int velocityY, int velocityZ, int data) {
super(entityId, entityUUID, entityType, x, y, z, yaw, pitch, headYaw, velocityX, velocityY, velocityZ, data);
}
@Override
public Object createPacket() {
net.minecraft.world.entity.EntityType<?> vanillaType = BuiltInRegistries.ENTITY_TYPE.getValue(CraftNamespacedKey.toMinecraft(entityType.getKey()));
return new ClientboundAddEntityPacket(
entityId,
entityUUID,
x,
y,
z,
AngelConverter.degreesToVanillaByte(pitch),
AngelConverter.degreesToVanillaByte(yaw),
vanillaType,
data,
new Vec3(velocityX, velocityY, velocityZ),
AngelConverter.degreesToVanillaByte(headYaw)
);
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundAddEntityPacket packet = (ClientboundAddEntityPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,22 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundClearDialogPacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.common.ClientboundClearDialogPacket;
import net.minecraft.server.level.ServerPlayer;
public class ClientboundClearDialogPacketImpl extends FS_ClientboundClearDialogPacket {
@Override
public Object createPacket() {
return ClientboundClearDialogPacket.INSTANCE;
}
@Override
protected void sendPacketTo(FS_RealPlayer player) {
ClientboundClearDialogPacket packet = (ClientboundClearDialogPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,128 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundCreateOrUpdateTeamPacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import io.papermc.paper.adventure.PaperAdventure;
import net.minecraft.ChatFormatting;
import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.Team;
public class ClientboundCreateOrUpdateTeamPacketImpl extends FS_ClientboundCreateOrUpdateTeamPacket {
private static final Scoreboard SCOREBOARD = new Scoreboard();
public ClientboundCreateOrUpdateTeamPacketImpl(String teamName, CreateTeam createTeam) {
super(teamName, createTeam);
}
public ClientboundCreateOrUpdateTeamPacketImpl(String teamName, RemoveTeam removeTeam) {
super(teamName, removeTeam);
}
public ClientboundCreateOrUpdateTeamPacketImpl(String teamName, UpdateTeam updateTeam) {
super(teamName, updateTeam);
}
public ClientboundCreateOrUpdateTeamPacketImpl(String teamName, AddEntity addEntity) {
super(teamName, addEntity);
}
public ClientboundCreateOrUpdateTeamPacketImpl(String teamName, RemoveEntity removeEntity) {
super(teamName, removeEntity);
}
@Override
public Object createPacket() {
return switch (method) {
case CREATE_TEAM -> createCreateTeamPacket();
case REMOVE_TEAM -> createRemoveTeamPacket();
case UPDATE_TEAM -> createUpdateTeamPacket();
case ADD_ENTITY -> createAddEntityPacket();
case REMOVE_ENTITY -> createRemoveEntityPacket();
};
}
private Object createCreateTeamPacket() {
if (createTeam == null) {
return null;
}
PlayerTeam playerTeam = new PlayerTeam(SCOREBOARD, teamName);
playerTeam.setDisplayName(PaperAdventure.asVanilla(createTeam.getDisplayName()));
playerTeam.setAllowFriendlyFire(createTeam.isAllowFriendlyFire());
playerTeam.setSeeFriendlyInvisibles(createTeam.isCanSeeFriendlyInvisibles());
playerTeam.setNameTagVisibility(Team.Visibility.valueOf(createTeam.getNameTagVisibility().getName()));
playerTeam.setCollisionRule(PlayerTeam.CollisionRule.valueOf(createTeam.getCollisionRule().getName()));
playerTeam.setColor(ChatFormatting.getById(createTeam.getColor().getId()));
playerTeam.setPlayerPrefix(PaperAdventure.asVanilla(createTeam.getPrefix()));
playerTeam.setPlayerSuffix(PaperAdventure.asVanilla(createTeam.getSuffix()));
for (String entity : createTeam.getEntities()) {
playerTeam.getPlayers().add(entity);
}
return ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true);
}
private Object createRemoveTeamPacket() {
if (removeTeam == null) {
return null;
}
PlayerTeam playerTeam = new PlayerTeam(SCOREBOARD, teamName);
return ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam);
}
private Object createUpdateTeamPacket() {
if (updateTeam == null) {
return null;
}
PlayerTeam playerTeam = new PlayerTeam(SCOREBOARD, teamName);
playerTeam.setDisplayName(PaperAdventure.asVanilla(updateTeam.getDisplayName()));
playerTeam.setAllowFriendlyFire(updateTeam.isAllowFriendlyFire());
playerTeam.setSeeFriendlyInvisibles(updateTeam.isCanSeeFriendlyInvisibles());
playerTeam.setNameTagVisibility(Team.Visibility.valueOf(updateTeam.getNameTagVisibility().getName()));
playerTeam.setCollisionRule(PlayerTeam.CollisionRule.valueOf(updateTeam.getCollisionRule().getName()));
playerTeam.setColor(ChatFormatting.getById(updateTeam.getColor().getId()));
playerTeam.setPlayerPrefix(PaperAdventure.asVanilla(updateTeam.getPrefix()));
playerTeam.setPlayerSuffix(PaperAdventure.asVanilla(updateTeam.getSuffix()));
return ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, true);
}
private Object createAddEntityPacket() {
if (addEntity == null) {
return null;
}
PlayerTeam playerTeam = new PlayerTeam(SCOREBOARD, teamName);
for (String entity : addEntity.getEntities()) {
playerTeam.getPlayers().add(entity);
}
return ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(playerTeam, addEntity.getEntities(), ClientboundSetPlayerTeamPacket.Action.ADD);
}
private Object createRemoveEntityPacket() {
if (removeEntity == null) {
return null;
}
PlayerTeam playerTeam = new PlayerTeam(SCOREBOARD, teamName);
for (String entity : removeEntity.getEntities()) {
playerTeam.getPlayers().add(entity);
}
return ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(playerTeam, removeEntity.getEntities(), ClientboundSetPlayerTeamPacket.Action.REMOVE);
}
@Override
protected void sendPacketTo(FS_RealPlayer player) {
ClientboundSetPlayerTeamPacket packet = (ClientboundSetPlayerTeamPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,30 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundPlayerInfoRemovePacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
import net.minecraft.server.level.ServerPlayer;
import java.util.List;
import java.util.UUID;
public class ClientboundPlayerInfoRemovePacketImpl extends FS_ClientboundPlayerInfoRemovePacket {
public ClientboundPlayerInfoRemovePacketImpl(List<UUID> uuids) {
super(uuids);
}
@Override
public Object createPacket() {
return new ClientboundPlayerInfoRemovePacket(uuids);
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundPlayerInfoRemovePacket packet = (ClientboundPlayerInfoRemovePacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,54 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundPlayerInfoUpdatePacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.GameProfileImpl;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import io.papermc.paper.adventure.PaperAdventure;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.GameType;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
public class ClientboundPlayerInfoUpdatePacketImpl extends FS_ClientboundPlayerInfoUpdatePacket {
public ClientboundPlayerInfoUpdatePacketImpl(EnumSet<Action> actions, List<Entry> entries) {
super(actions, entries);
}
@Override
public Object createPacket() {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> vanillaActions = EnumSet.noneOf(ClientboundPlayerInfoUpdatePacket.Action.class);
for (FS_ClientboundPlayerInfoUpdatePacket.Action action : actions) {
vanillaActions.add(ClientboundPlayerInfoUpdatePacket.Action.valueOf(action.name()));
}
List<ClientboundPlayerInfoUpdatePacket.Entry> entries = new ArrayList<>();
for (Entry entry : this.entries) {
entries.add(new ClientboundPlayerInfoUpdatePacket.Entry(
entry.uuid(),
GameProfileImpl.asVanilla(entry.profile()),
entry.listed(),
entry.latency(),
GameType.byId(entry.gameMode().getId()),
PaperAdventure.asVanilla(entry.displayName()),
true,
-1,
null // TODO: Add ChatSession support
));
}
return new ClientboundPlayerInfoUpdatePacket(vanillaActions, entries);
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,37 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundRemoveEntitiesPacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.server.level.ServerPlayer;
import java.util.List;
public class ClientboundRemoveEntitiesPacketImpl extends FS_ClientboundRemoveEntitiesPacket {
/**
* @param entityIds IDs of the entities to remove
*/
public ClientboundRemoveEntitiesPacketImpl(List<Integer> entityIds) {
super(entityIds);
}
@Override
public Object createPacket() {
int[] ids = new int[this.entityIds.size()];
for (int i = 0; i < this.entityIds.size(); i++) {
ids[i] = this.entityIds.get(i);
}
return new ClientboundRemoveEntitiesPacket(ids);
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundRemoveEntitiesPacket packet = (ClientboundRemoveEntitiesPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,38 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundRotateHeadPacket;
import de.oliver.fancysitula.api.utils.AngelConverter;
import de.oliver.fancysitula.api.utils.reflections.ReflectionUtils;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
import net.minecraft.server.level.ServerPlayer;
public class ClientboundRotateHeadPacketImpl extends FS_ClientboundRotateHeadPacket {
public ClientboundRotateHeadPacketImpl(int entityId, float headYaw) {
super(entityId, headYaw);
}
@Override
public Object createPacket() {
ClientboundRotateHeadPacket packet = null;
try {
packet = ReflectionUtils.createUnsafeInstance(ClientboundRotateHeadPacket.class);
ReflectionUtils.setFinalField(packet, "entityId", entityId);
ReflectionUtils.setFinalField(packet, "yHeadRot", AngelConverter.degreesToVanillaByte(headYaw));
} catch (Exception e) {
e.printStackTrace();
}
return packet;
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundRotateHeadPacket packet = (ClientboundRotateHeadPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,67 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundSetEntityDataPacket;
import de.oliver.fancysitula.api.utils.reflections.ReflectionUtils;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.text.Component;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
public class ClientboundSetEntityDataPacketImpl extends FS_ClientboundSetEntityDataPacket {
public ClientboundSetEntityDataPacketImpl(int entityId, List<EntityData> entityData) {
super(entityId, entityData);
}
@Override
public Object createPacket() {
List<SynchedEntityData.DataValue<?>> dataValues = new ArrayList<>();
for (EntityData data : entityData) {
try {
Class<?> entityClass = Class.forName(data.getAccessor().entityClassName());
net.minecraft.network.syncher.EntityDataAccessor<Object> accessor = ReflectionUtils.getStaticField(entityClass, data.getAccessor().accessorFieldName());
Object vanillaValue = data.getValue();
if (data.getValue() == null) {
continue;
}
if (data.getValue() instanceof Component c) {
vanillaValue = PaperAdventure.asVanilla(c);
}
if (data.getValue() instanceof ItemStack i) {
vanillaValue = net.minecraft.world.item.ItemStack.fromBukkitCopy(i);
}
if (data.getValue() instanceof BlockState b) {
vanillaValue = ((CraftBlockState) b).getHandle();
}
dataValues.add(SynchedEntityData.DataValue.create(accessor, vanillaValue));
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
return new ClientboundSetEntityDataPacket(entityId, dataValues);
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundSetEntityDataPacket packet = (ClientboundSetEntityDataPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,45 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import com.mojang.datafixers.util.Pair;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundSetEquipmentPacket;
import de.oliver.fancysitula.api.utils.FS_EquipmentSlot;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.EquipmentSlot;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ClientboundSetEquipmentPacketImpl extends FS_ClientboundSetEquipmentPacket {
public ClientboundSetEquipmentPacketImpl(int entityId, Map<FS_EquipmentSlot, ItemStack> equipment) {
super(entityId, equipment);
}
@Override
public Object createPacket() {
List<Pair<net.minecraft.world.entity.EquipmentSlot, net.minecraft.world.item.ItemStack>> slots = new ArrayList<>();
for (Map.Entry<FS_EquipmentSlot, ItemStack> entry : equipment.entrySet()) {
EquipmentSlot equipmentSlot = net.minecraft.world.entity.EquipmentSlot.byName(entry.getKey().name().toLowerCase());
net.minecraft.world.item.ItemStack itemStack = CraftItemStack.asNMSCopy(entry.getValue());
slots.add(Pair.of(equipmentSlot, itemStack));
}
return new ClientboundSetEquipmentPacket(entityId, slots);
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundSetEquipmentPacket packet = (ClientboundSetEquipmentPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,45 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundSetPassengersPacket;
import de.oliver.fancysitula.api.utils.reflections.ReflectionUtils;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
import net.minecraft.server.level.ServerPlayer;
import java.util.List;
public class ClientboundSetPassengersPacketImpl extends FS_ClientboundSetPassengersPacket {
public ClientboundSetPassengersPacketImpl(int entityId, List<Integer> passengers) {
super(entityId, passengers);
}
@Override
public Object createPacket() {
int[] passengers = new int[this.passengers.size()];
for (int i = 0; i < this.passengers.size(); i++) {
passengers[i] = this.passengers.get(i);
}
try {
ClientboundSetPassengersPacket packet = ReflectionUtils.createUnsafeInstance(ClientboundSetPassengersPacket.class);
ReflectionUtils.setFinalField(packet, "vehicle", entityId);
ReflectionUtils.setFinalField(packet, "passengers", passengers);
return packet;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundSetPassengersPacket packet = (ClientboundSetPassengersPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,276 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.dialogs.FS_CommonDialogData;
import de.oliver.fancysitula.api.dialogs.FS_Dialog;
import de.oliver.fancysitula.api.dialogs.FS_DialogAction;
import de.oliver.fancysitula.api.dialogs.actions.FS_CommonButtonData;
import de.oliver.fancysitula.api.dialogs.actions.FS_DialogActionButton;
import de.oliver.fancysitula.api.dialogs.actions.FS_DialogCustomAction;
import de.oliver.fancysitula.api.dialogs.body.FS_DialogBody;
import de.oliver.fancysitula.api.dialogs.body.FS_DialogItemBody;
import de.oliver.fancysitula.api.dialogs.body.FS_DialogTextBody;
import de.oliver.fancysitula.api.dialogs.inputs.*;
import de.oliver.fancysitula.api.dialogs.types.FS_ConfirmationDialog;
import de.oliver.fancysitula.api.dialogs.types.FS_DialogListDialog;
import de.oliver.fancysitula.api.dialogs.types.FS_MultiActionDialog;
import de.oliver.fancysitula.api.dialogs.types.FS_NoticeDialog;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundShowDialogPacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.common.ClientboundShowDialogPacket;
import net.minecraft.resources.Identifier;
import net.minecraft.server.dialog.*;
import net.minecraft.server.dialog.action.Action;
import net.minecraft.server.dialog.action.CustomAll;
import net.minecraft.server.dialog.body.DialogBody;
import net.minecraft.server.dialog.body.ItemBody;
import net.minecraft.server.dialog.body.PlainMessage;
import net.minecraft.server.dialog.input.*;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ClientboundShowDialogPacketImpl extends FS_ClientboundShowDialogPacket {
public ClientboundShowDialogPacketImpl(FS_Dialog dialog) {
super(dialog);
}
@Override
public Object createPacket() {
Holder<Dialog> holder = Holder.direct(toNms(dialog));
return new ClientboundShowDialogPacket(holder);
}
@Override
protected void sendPacketTo(FS_RealPlayer player) {
ClientboundShowDialogPacket packet = (ClientboundShowDialogPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
private Dialog toNms(FS_Dialog dialog) {
if (dialog instanceof FS_NoticeDialog notice) {
return noticeToNms(notice);
} else if (dialog instanceof FS_ConfirmationDialog confirmation) {
return confirmationToNms(confirmation);
} else if (dialog instanceof FS_DialogListDialog dialogList) {
return dialogListToNms(dialogList);
} else if (dialog instanceof FS_MultiActionDialog multiActionDialog) {
return multiActionDialogToNms(multiActionDialog);
}
return null;
}
private Dialog noticeToNms(FS_NoticeDialog notice) {
CommonDialogData common = commonToNms(notice.getDialogData());
ActionButton actionButton = actionButtonToNms(notice.getActionButton());
return new NoticeDialog(common, actionButton);
}
private Dialog confirmationToNms(FS_ConfirmationDialog notice) {
CommonDialogData common = commonToNms(notice.getDialogData());
ActionButton yes = actionButtonToNms(notice.getYesButton());
ActionButton no = actionButtonToNms(notice.getNoButton());
return new ConfirmationDialog(common, yes, no);
}
private Dialog dialogListToNms(FS_DialogListDialog dialogList) {
CommonDialogData common = commonToNms(dialogList.getDialogData());
List<Holder<Dialog>> dialogs = new ArrayList<>();
for (FS_Dialog dialog : dialogList.getDialogs()) {
dialogs.add(Holder.direct(toNms(dialog)));
}
HolderSet<Dialog> dialogSet = HolderSet.direct(dialogs);
Optional<ActionButton> exitButton = dialogList.getExitButton() != null ?
Optional.of(actionButtonToNms(dialogList.getExitButton())) :
Optional.empty();
return new DialogListDialog(common, dialogSet, exitButton, dialogList.getColumns(), dialogList.getButtonWidth());
}
private Dialog multiActionDialogToNms(FS_MultiActionDialog multiActionDialog) {
CommonDialogData common = commonToNms(multiActionDialog.getDialogData());
List<ActionButton> actionButtons = new ArrayList<>();
for (FS_DialogActionButton actionButton : multiActionDialog.getActions()) {
actionButtons.add(actionButtonToNms(actionButton));
}
Optional<ActionButton> exitAction = multiActionDialog.getExitAction() != null ?
Optional.of(actionButtonToNms(multiActionDialog.getExitAction())) :
Optional.empty();
return new MultiActionDialog(common, actionButtons, exitAction, multiActionDialog.getColumns());
}
private CommonDialogData commonToNms(FS_CommonDialogData dialogData) {
Component title = PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(dialogData.getTitle()));
Optional<Component> externalTitle = dialogData.getExternalTitle() != null ?
Optional.of(PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(dialogData.getExternalTitle()))) :
Optional.empty();
return new CommonDialogData(
title,
externalTitle,
dialogData.isCanCloseWithEscape(),
dialogData.isPause(),
actionToNms(dialogData.getAfterAction()),
bodyToNms(dialogData.getBody()),
inputsToNms(dialogData.getInputs())
);
}
private DialogAction actionToNms(FS_DialogAction dialogAction) {
return switch (dialogAction) {
case CLOSE -> DialogAction.CLOSE;
case NONE -> DialogAction.NONE;
case WAIT_FOR_RESPONSE -> DialogAction.WAIT_FOR_RESPONSE;
};
}
private List<DialogBody> bodyToNms(List<FS_DialogBody> bodies) {
List<DialogBody> nmsBodies = new ArrayList<>();
for (FS_DialogBody body : bodies) {
if (body instanceof FS_DialogTextBody textBody) {
nmsBodies.add(new PlainMessage(
PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(textBody.getText())),
textBody.getWidth()
));
} else if (body instanceof FS_DialogItemBody itemBody) {
Optional<PlainMessage> description = itemBody.getDescription() != null ?
Optional.of(new PlainMessage(
PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(itemBody.getDescription().getText())),
itemBody.getDescription().getWidth()
)) :
Optional.empty();
nmsBodies.add(new ItemBody(
CraftItemStack.asNMSCopy(itemBody.getItem()),
description,
itemBody.isShowDecorations(),
itemBody.isShowTooltip(),
itemBody.getWidth(),
itemBody.getHeight()
));
}
}
return nmsBodies;
}
private List<Input> inputsToNms(List<FS_DialogInput> inputs) {
List<Input> nmsInputs = new ArrayList<>();
for (FS_DialogInput input : inputs) {
String key = input.getKey();
InputControl control = null;
if (input.getControl() instanceof FS_DialogBooleanInput booleanInput) {
control = new BooleanInput(
PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(booleanInput.getLabel())),
booleanInput.isInitial(),
booleanInput.getOnTrue(),
booleanInput.getOnFalse()
);
} else if (input.getControl() instanceof FS_DialogNumberRangeInput numberRangeInput) {
control = new NumberRangeInput(
numberRangeInput.getWidth(),
PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(numberRangeInput.getLabel())),
numberRangeInput.getLabelFormat(),
new NumberRangeInput.RangeInfo(
numberRangeInput.getStart(),
numberRangeInput.getEnd(),
numberRangeInput.getInitial() != null ? Optional.of(numberRangeInput.getInitial()) : Optional.empty(),
numberRangeInput.getStep() != null ? Optional.of(numberRangeInput.getStep()) : Optional.empty()
)
);
} else if (input.getControl() instanceof FS_DialogSingleOptionInput singleOptionInput) {
List<SingleOptionInput.Entry> nmsEntries = new ArrayList<>();
for (FS_DialogSingleOptionInput.Entry entry : singleOptionInput.getEntries()) {
nmsEntries.add(new SingleOptionInput.Entry(
entry.getId(),
entry.getDisplay() != null ? Optional.of(PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(entry.getDisplay()))) : Optional.empty(),
entry.isInitial()
));
}
control = new SingleOptionInput(
singleOptionInput.getWidth(),
nmsEntries,
PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(singleOptionInput.getLabel())),
singleOptionInput.isLabelVisible()
);
} else if (input.getControl() instanceof FS_DialogTextInput textInput) {
control = new TextInput(
textInput.getWidth(),
PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(textInput.getLabel())),
textInput.isLabelVisible(),
textInput.getInitial(),
textInput.getMaxLength(),
Optional.empty()
);
}
nmsInputs.add(new Input(key, control));
}
return nmsInputs;
}
private ActionButton actionButtonToNms(FS_DialogActionButton actionButton) {
CommonButtonData buttonData = commonButtonDataToNms(actionButton.getButtonData());
Action action = null;
if (actionButton.getAction() instanceof FS_DialogCustomAction customAction) {
Key idKey = Key.key("fancysitula", customAction.getId());
Identifier idLocation = PaperAdventure.asVanilla(idKey);
Optional<CompoundTag> additions;
if (customAction.getAdditions() != null) {
CompoundTag tag = new CompoundTag();
customAction.getAdditions().forEach(tag::putString);
additions = Optional.of(tag);
} else {
additions = Optional.empty();
}
action = new CustomAll(idLocation, additions);
}
Optional<Action> optionalAction = action != null ?
Optional.of(action) :
Optional.empty();
return new ActionButton(buttonData, optionalAction);
}
private CommonButtonData commonButtonDataToNms(FS_CommonButtonData commonButtonData) {
Component label = PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(commonButtonData.getLabel()));
Optional<Component> tooltip = commonButtonData.getTooltip() != null ?
Optional.of(PaperAdventure.asVanilla(MiniMessage.miniMessage().deserialize(commonButtonData.getTooltip()))) :
Optional.empty();
int width = commonButtonData.getWidth();
return new CommonButtonData(label, tooltip, width);
}
}

View File

@@ -0,0 +1,43 @@
package de.oliver.fancysitula.versions.v1_21_11.packets;
import de.oliver.fancysitula.api.entities.FS_RealPlayer;
import de.oliver.fancysitula.api.packets.FS_ClientboundTeleportEntityPacket;
import de.oliver.fancysitula.versions.v1_21_11.utils.VanillaPlayerAdapter;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.phys.Vec3;
import java.util.Set;
public class ClientboundTeleportEntityPacketImpl extends FS_ClientboundTeleportEntityPacket {
public ClientboundTeleportEntityPacketImpl(int entityId, double x, double y, double z, float yaw, float pitch, boolean onGround) {
super(entityId, x, y, z, yaw, pitch, onGround);
}
@Override
public Object createPacket() {
ClientboundTeleportEntityPacket packet = new ClientboundTeleportEntityPacket(
entityId,
new PositionMoveRotation(
new Vec3(x, y, z),
Vec3.ZERO,
yaw,
pitch
),
Set.of(),
onGround
);
return packet;
}
@Override
public void sendPacketTo(FS_RealPlayer player) {
ClientboundTeleportEntityPacket packet = (ClientboundTeleportEntityPacket) createPacket();
ServerPlayer vanillaPlayer = VanillaPlayerAdapter.asVanilla(player.getBukkitPlayer());
vanillaPlayer.connection.send(packet);
}
}

View File

@@ -0,0 +1,33 @@
package de.oliver.fancysitula.versions.v1_21_11.utils;
import com.mojang.authlib.GameProfile;
import de.oliver.fancysitula.api.utils.FS_GameProfile;
import java.util.Map;
public class GameProfileImpl {
public static GameProfile asVanilla(FS_GameProfile gameProfile) {
GameProfile gf = new GameProfile(gameProfile.getUUID(), gameProfile.getName());
for (Map.Entry<String, FS_GameProfile.Property> entry : gameProfile.getProperties().entrySet()) {
FS_GameProfile.Property property = entry.getValue();
gf.properties().put(entry.getKey(), new com.mojang.authlib.properties.Property(property.name(), property.value(), property.signature()));
}
return gf;
}
public static FS_GameProfile fromVanilla(GameProfile gameProfile) {
FS_GameProfile fsGameProfile = new FS_GameProfile(gameProfile.id(), gameProfile.name());
for (Map.Entry<String, com.mojang.authlib.properties.Property> entry : gameProfile.properties().entries()) {
com.mojang.authlib.properties.Property property = entry.getValue();
fsGameProfile.getProperties().put(entry.getKey(), new FS_GameProfile.Property(property.name(), property.value(), property.signature()));
}
return fsGameProfile;
}
}

View File

@@ -0,0 +1,110 @@
package de.oliver.fancysitula.versions.v1_21_11.utils;
import de.oliver.fancysitula.api.packets.FS_ServerboundCustomClickActionPacket;
import de.oliver.fancysitula.api.packets.FS_ServerboundPacket;
import de.oliver.fancysitula.api.utils.FS_PacketListener;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.papermc.paper.adventure.PaperAdventure;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.common.ServerboundCustomClickActionPacket;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PacketListenerImpl extends FS_PacketListener {
private static final String PIPELINE_NAME = "fancysitula-packet-injector";
public PacketListenerImpl(FS_ServerboundPacket.Type packet) {
super(packet);
}
@Override
public void inject(Player player) {
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
Channel channel = serverPlayer.connection.connection.channel;
if (channel.pipeline().get(PIPELINE_NAME) != null) {
return;
}
channel.pipeline().addAfter("decoder", PIPELINE_NAME, new MessageToMessageDecoder<Packet<?>>() {
@Override
protected void decode(ChannelHandlerContext ctx, Packet<?> msg, List<Object> out) {
out.add(msg);
FS_ServerboundPacket.Type packetType = getPacketType(msg);
if (packetType == null) {
return; // Unsupported packet type
}
if (packet == FS_ServerboundPacket.Type.ALL) {
FS_ServerboundPacket fsPacket = convert(packetType, msg);
PacketReceivedEvent packetReceivedEvent = new PacketReceivedEvent(fsPacket, player);
listeners.forEach(listener -> listener.accept(packetReceivedEvent));
return;
}
if (packet == packetType) {
FS_ServerboundPacket fsPacket = convert(packetType, msg);
PacketReceivedEvent packetReceivedEvent = new PacketReceivedEvent(fsPacket, player);
listeners.forEach(listener -> listener.accept(packetReceivedEvent));
}
}
});
}
private FS_ServerboundPacket.Type getPacketType(Packet<?> packet) {
String className = packet.getClass().getSimpleName();
for (FS_ServerboundPacket.Type type : FS_ServerboundPacket.Type.values()) {
if (type.getPacketClassName().equalsIgnoreCase(className)) {
return type;
}
}
return null;
}
private FS_ServerboundPacket convert(FS_ServerboundPacket.Type type, Packet<?> packet) {
switch (type) {
case CUSTOM_CLICK_ACTION -> {
ServerboundCustomClickActionPacket customClickActionPacket = (ServerboundCustomClickActionPacket) packet;
Map<String, String> payload = new HashMap<>();
if (customClickActionPacket.payload().isPresent() && customClickActionPacket.payload().get().asCompound().isPresent()) {
customClickActionPacket.payload().get().asCompound().get().forEach((k, v) -> {
if (v.getType().getName().equals(StringTag.TYPE.getName())) {
if (v.asString().isPresent()) {
payload.put(k, v.asString().get());
}
} else if (v.getType().getName().equals(net.minecraft.nbt.ByteTag.TYPE.getName())) {
if (v.asBoolean().isPresent()) {
payload.put(k, String.valueOf(v.asBoolean().get()));
} else if (v.asByte().isPresent()) {
payload.put(k, String.valueOf(v.asByte().get()));
}
} else {
payload.put(k, v.toString());
}
});
}
return new FS_ServerboundCustomClickActionPacket(
type,
PaperAdventure.asAdventure(customClickActionPacket.id()),
payload
);
}
// Add more cases for other packet types as needed
default -> throw new IllegalArgumentException("Unsupported packet type: " + type);
}
}
}

View File

@@ -0,0 +1,12 @@
package de.oliver.fancysitula.versions.v1_21_11.utils;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class VanillaPlayerAdapter {
public static ServerPlayer asVanilla(Player p) {
return ((CraftPlayer) p).getHandle();
}
}

View File

@@ -0,0 +1,65 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.utils.AngelConverter;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundAddEntityPacketImpl;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import org.bukkit.entity.EntityType;
import java.util.UUID;
class ClientboundAddEntityPacketImplTest {
//TODO: Fix this test (registry problems)
// @Test
void createPacket() {
int entityId = 10000;
UUID entityUUID = UUID.randomUUID();
EntityType entityType = EntityType.PIG;
double x = 5;
double y = 57;
double z = 203;
float yaw = 142;
float pitch = 247;
float headYaw = 90;
int velocityX = 0;
int velocityY = 0;
int velocityZ = 0;
int data = 0;
ClientboundAddEntityPacketImpl packet = new ClientboundAddEntityPacketImpl(
entityId,
entityUUID,
entityType,
x,
y,
z,
yaw,
pitch,
headYaw,
velocityX,
velocityY,
velocityZ,
data
);
ClientboundAddEntityPacket createdPacket = (ClientboundAddEntityPacket) packet.createPacket();
assert createdPacket.getId() == entityId;
assert createdPacket.getUUID().equals(entityUUID);
assert createdPacket.getType().getDescriptionId().equals(entityType.getKey().getKey());
assert createdPacket.getX() == x;
assert createdPacket.getY() == y;
assert createdPacket.getZ() == z;
assert createdPacket.getYRot() == AngelConverter.degreesToVanillaByte(yaw);
assert createdPacket.getXRot() == AngelConverter.degreesToVanillaByte(pitch);
assert createdPacket.getYHeadRot() == AngelConverter.degreesToVanillaByte(headYaw);
assert createdPacket.getMovement().x == velocityX;
assert createdPacket.getMovement().y == velocityY;
assert createdPacket.getMovement().z == velocityZ;
assert createdPacket.getData() == data;
}
}

View File

@@ -0,0 +1,15 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundClearDialogPacketImpl;
import org.junit.jupiter.api.Test;
public class ClientboundClearDialogPacketImplTest {
@Test
void createPacket() {
ClientboundClearDialogPacketImpl packet = new ClientboundClearDialogPacketImpl();
assert packet.createPacket() != null : "Packet creation failed";
// assert packet.equals(ClientboundClearDialogPacket.INSTANCE);
}
}

View File

@@ -0,0 +1,23 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundPlayerInfoRemovePacketImpl;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.UUID;
class ClientboundPlayerInfoRemovePacketImplTest {
@Test
void createPacket() {
List<UUID> uuids = List.of(UUID.randomUUID(), UUID.randomUUID());
ClientboundPlayerInfoRemovePacketImpl packet = new ClientboundPlayerInfoRemovePacketImpl(uuids);
ClientboundPlayerInfoRemovePacket vanillaPacket = (ClientboundPlayerInfoRemovePacket) packet.createPacket();
for (UUID uuid : uuids) {
assert vanillaPacket.profileIds().contains(uuid);
}
}
}

View File

@@ -0,0 +1,62 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.packets.FS_ClientboundPlayerInfoUpdatePacket;
import de.oliver.fancysitula.api.utils.FS_GameProfile;
import de.oliver.fancysitula.api.utils.FS_GameType;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundPlayerInfoUpdatePacketImpl;
import net.kyori.adventure.text.Component;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
class ClientboundPlayerInfoUpdatePacketImplTest {
@Test
void createPacket() {
// Setup packet
EnumSet<FS_ClientboundPlayerInfoUpdatePacket.Action> actions = EnumSet.noneOf(FS_ClientboundPlayerInfoUpdatePacket.Action.class);
actions.add(FS_ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER);
actions.add(FS_ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
actions.add(FS_ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
FS_GameProfile gameProfile = new FS_GameProfile(UUID.randomUUID(), "Test name");
boolean listed = true;
int latency = 42;
FS_GameType gameMode = FS_GameType.SURVIVAL;
Component displayName = Component.text("Test displayname");
List<FS_ClientboundPlayerInfoUpdatePacket.Entry> entries = new ArrayList<>();
entries.add(new FS_ClientboundPlayerInfoUpdatePacket.Entry(
gameProfile.getUUID(),
gameProfile,
listed,
latency,
gameMode,
displayName
));
ClientboundPlayerInfoUpdatePacketImpl packet = new ClientboundPlayerInfoUpdatePacketImpl(actions, entries);
ClientboundPlayerInfoUpdatePacket createdPacket = (ClientboundPlayerInfoUpdatePacket) packet.createPacket();
assert createdPacket.entries().size() == 1;
assert createdPacket.actions().size() == 3;
// check entry
ClientboundPlayerInfoUpdatePacket.Entry entry = createdPacket.entries().getFirst();
assert entry.profile().id().equals(gameProfile.getUUID());
assert entry.profile().name().equals(gameProfile.getName());
assert entry.listed() == listed;
assert entry.latency() == latency;
assert entry.gameMode().getId() == gameMode.getId();
// check actions
assert createdPacket.actions().contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER);
assert createdPacket.actions().contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
assert createdPacket.actions().contains(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
}
}

View File

@@ -0,0 +1,21 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundRemoveEntitiesPacketImpl;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import org.junit.jupiter.api.Test;
import java.util.List;
class ClientboundRemoveEntitiesPacketImplTest {
@Test
void createPacket() {
List<Integer> entityIds = List.of(95, 120, 154, 187);
ClientboundRemoveEntitiesPacketImpl packet = new ClientboundRemoveEntitiesPacketImpl(entityIds);
ClientboundRemoveEntitiesPacket createdPacket = (ClientboundRemoveEntitiesPacket) packet.createPacket();
assert createdPacket.getEntityIds().size() == entityIds.size();
assert createdPacket.getEntityIds().containsAll(entityIds);
}
}

View File

@@ -0,0 +1,21 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.utils.reflections.ReflectionUtils;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundRotateHeadPacketImpl;
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;
import org.junit.jupiter.api.Test;
class ClientboundRotateHeadPacketImplTest {
@Test
void createPacket() throws Exception {
int entityId = 184;
float headYaw = 45;
ClientboundRotateHeadPacketImpl packet = new ClientboundRotateHeadPacketImpl(entityId, (byte) headYaw);
ClientboundRotateHeadPacket createdPacket = (ClientboundRotateHeadPacket) packet.createPacket();
assert ReflectionUtils.getField(createdPacket, "entityId").equals(entityId);
assert createdPacket.getYHeadRot() == headYaw;
}
}

View File

@@ -0,0 +1,29 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.packets.FS_ClientboundSetEntityDataPacket;
import de.oliver.fancysitula.api.utils.entityData.FS_TextDisplayData;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundSetEntityDataPacketImpl;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import java.util.List;
class ClientboundSetEntityDataPacketImplTest {
//TODO: Fix this test (using registry)
// @Test
void createPacket() {
int entityId = 712;
List<FS_ClientboundSetEntityDataPacket.EntityData> entityData = List.of(
new FS_ClientboundSetEntityDataPacket.EntityData(
FS_TextDisplayData.TEXT,
"Hello, World!"
)
);
ClientboundSetEntityDataPacketImpl packet = new ClientboundSetEntityDataPacketImpl(entityId, entityData);
ClientboundSetEntityDataPacket createdPacket = (ClientboundSetEntityDataPacket) packet.createPacket();
assert createdPacket.id() == entityId;
assert createdPacket.packedItems().size() == 1;
}
}

View File

@@ -0,0 +1,29 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.utils.FS_EquipmentSlot;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundSetEquipmentPacketImpl;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import java.util.Map;
class ClientboundSetEquipmentPacketImplTest {
//TODO: Fix this test (registry problems)
// @Test
void createPacket() {
// Setup packet
Map<FS_EquipmentSlot, ItemStack> equipment = Map.of(
FS_EquipmentSlot.MAINHAND, new ItemStack(Material.DIAMOND_SWORD),
FS_EquipmentSlot.OFFHAND, new ItemStack(Material.SHIELD),
FS_EquipmentSlot.HEAD, new ItemStack(Material.DIAMOND_HELMET)
);
ClientboundSetEquipmentPacketImpl packet = new ClientboundSetEquipmentPacketImpl(42, equipment);
ClientboundSetEquipmentPacket createdPacket = (ClientboundSetEquipmentPacket) packet.createPacket();
assert createdPacket.getEntity() == 42;
assert createdPacket.getSlots().size() == 3;
}
}

View File

@@ -0,0 +1,29 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundSetPassengersPacketImpl;
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
public class ClientboundSetPassengersPacketImplTest {
@Test
void createPacket() {
// Setup packet
int vehicleID = 712;
List<Integer> passengers = new ArrayList<>();
passengers.add(571);
passengers.add(572);
ClientboundSetPassengersPacketImpl packet = new ClientboundSetPassengersPacketImpl(vehicleID, passengers);
ClientboundSetPassengersPacket createdPacket = (ClientboundSetPassengersPacket) packet.createPacket();
// Check packet
assert createdPacket.getVehicle() == vehicleID;
assert createdPacket.getPassengers().length == 2;
assert createdPacket.getPassengers()[0] == 571;
assert createdPacket.getPassengers()[1] == 572;
}
}

View File

@@ -0,0 +1,31 @@
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundTeleportEntityPacketImpl;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import org.junit.jupiter.api.Test;
class ClientboundTeleportEntityPacketImplTest {
@Test
void createPacket() {
int entityId = 4313;
double x = 15.0;
double y = 57.0;
double z = -27.0;
float yaw = 90.0f;
float pitch = 45.0f;
boolean onGround = true;
ClientboundTeleportEntityPacketImpl packet = new ClientboundTeleportEntityPacketImpl(entityId, x, y, z, yaw, pitch, onGround);
ClientboundTeleportEntityPacket createdPacket = (ClientboundTeleportEntityPacket) packet.createPacket();
assert createdPacket != null;
assert createdPacket.id() == entityId;
assert createdPacket.change().position().x == x;
assert createdPacket.change().position().y == y;
assert createdPacket.change().position().z == z;
assert createdPacket.change().xRot() == pitch;
assert createdPacket.change().yRot() == yaw;
assert createdPacket.onGround() == onGround;
}
}

View File

@@ -7,6 +7,7 @@ import java.util.List;
public enum ServerVersion { public enum ServerVersion {
v1_21_11("1.21.11", 774),
v1_21_10("1.21.10", 773), v1_21_10("1.21.10", 773),
v1_21_9("1.21.9", 773), v1_21_9("1.21.9", 773),
v1_21_8("1.21.8", 772), v1_21_8("1.21.8", 772),

View File

@@ -28,6 +28,9 @@ public class PacketFactory {
List<FS_ClientboundPlayerInfoUpdatePacket.Entry> entries List<FS_ClientboundPlayerInfoUpdatePacket.Entry> entries
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundPlayerInfoUpdatePacketImpl(actions, entries);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundPlayerInfoUpdatePacketImpl(actions, entries); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundPlayerInfoUpdatePacketImpl(actions, entries);
} }
@@ -73,6 +76,9 @@ public class PacketFactory {
int velocityZ, int velocityZ,
int data) { int data) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundAddEntityPacketImpl(entityId, entityUUID, entityType, x, y, z, yaw, pitch, headYaw, velocityX, velocityY, velocityZ, data);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundAddEntityPacketImpl(entityId, entityUUID, entityType, x, y, z, yaw, pitch, headYaw, velocityX, velocityY, velocityZ, data); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundAddEntityPacketImpl(entityId, entityUUID, entityType, x, y, z, yaw, pitch, headYaw, velocityX, velocityY, velocityZ, data);
} }
@@ -105,6 +111,9 @@ public class PacketFactory {
List<UUID> uuids List<UUID> uuids
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundPlayerInfoRemovePacketImpl(uuids);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundPlayerInfoRemovePacketImpl(uuids); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundPlayerInfoRemovePacketImpl(uuids);
} }
@@ -137,6 +146,9 @@ public class PacketFactory {
List<Integer> entityIds List<Integer> entityIds
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundRemoveEntitiesPacketImpl(entityIds);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundRemoveEntitiesPacketImpl(entityIds); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundRemoveEntitiesPacketImpl(entityIds);
} }
@@ -181,6 +193,9 @@ public class PacketFactory {
boolean onGround boolean onGround
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundTeleportEntityPacketImpl(entityId, x, y, z, yaw, pitch, onGround);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundTeleportEntityPacketImpl(entityId, x, y, z, yaw, pitch, onGround); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundTeleportEntityPacketImpl(entityId, x, y, z, yaw, pitch, onGround);
} }
@@ -215,6 +230,9 @@ public class PacketFactory {
float headYaw float headYaw
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundRotateHeadPacketImpl(entityId, headYaw);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundRotateHeadPacketImpl(entityId, headYaw); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundRotateHeadPacketImpl(entityId, headYaw);
} }
@@ -249,6 +267,9 @@ public class PacketFactory {
List<FS_ClientboundSetEntityDataPacket.EntityData> entityData List<FS_ClientboundSetEntityDataPacket.EntityData> entityData
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundSetEntityDataPacketImpl(entityId, entityData);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetEntityDataPacketImpl(entityId, entityData); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetEntityDataPacketImpl(entityId, entityData);
} }
@@ -283,6 +304,9 @@ public class PacketFactory {
Map<FS_EquipmentSlot, ItemStack> equipment Map<FS_EquipmentSlot, ItemStack> equipment
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundSetEquipmentPacketImpl(entityId, equipment);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetEquipmentPacketImpl(entityId, equipment); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetEquipmentPacketImpl(entityId, equipment);
} }
@@ -317,6 +341,9 @@ public class PacketFactory {
List<Integer> passengers List<Integer> passengers
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundSetPassengersPacketImpl(entityId, passengers);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetPassengersPacketImpl(entityId, passengers); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetPassengersPacketImpl(entityId, passengers);
} }
@@ -354,6 +381,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.CreateTeam createTeam FS_ClientboundCreateOrUpdateTeamPacket.CreateTeam createTeam
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, createTeam);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, createTeam); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, createTeam);
} }
@@ -390,6 +420,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.RemoveTeam removeTeam FS_ClientboundCreateOrUpdateTeamPacket.RemoveTeam removeTeam
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeTeam);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeTeam); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeTeam);
} }
@@ -426,6 +459,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.UpdateTeam updateTeam FS_ClientboundCreateOrUpdateTeamPacket.UpdateTeam updateTeam
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, updateTeam);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, updateTeam); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, updateTeam);
} }
@@ -462,6 +498,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.AddEntity addEntity FS_ClientboundCreateOrUpdateTeamPacket.AddEntity addEntity
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, addEntity);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, addEntity); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, addEntity);
} }
@@ -498,6 +537,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.RemoveEntity removeEntity FS_ClientboundCreateOrUpdateTeamPacket.RemoveEntity removeEntity
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeEntity);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeEntity); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeEntity);
} }
@@ -531,6 +573,9 @@ public class PacketFactory {
FS_Dialog dialog FS_Dialog dialog
) { ) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundShowDialogPacketImpl(dialog);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundShowDialogPacketImpl(dialog); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundShowDialogPacketImpl(dialog);
} }
@@ -549,6 +594,9 @@ public class PacketFactory {
*/ */
public FS_ClientboundClearDialogPacket createClearDialogPacket() { public FS_ClientboundClearDialogPacket createClearDialogPacket() {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.packets.ClientboundClearDialogPacketImpl();
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundClearDialogPacketImpl(); return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundClearDialogPacketImpl();
} }

View File

@@ -8,6 +8,9 @@ public class PacketListenerFactory {
public FS_PacketListener createPacketListener(FS_ServerboundPacket.Type packet) { public FS_PacketListener createPacketListener(FS_ServerboundPacket.Type packet) {
switch (ServerVersion.getCurrentVersion()) { switch (ServerVersion.getCurrentVersion()) {
case v1_21_11 -> {
return new de.oliver.fancysitula.versions.v1_21_11.utils.PacketListenerImpl(packet);
}
case v1_21_9, v1_21_10 -> { case v1_21_9, v1_21_10 -> {
return new de.oliver.fancysitula.versions.v1_21_9.utils.PacketListenerImpl(packet); return new de.oliver.fancysitula.versions.v1_21_9.utils.PacketListenerImpl(packet);
} }

View File

@@ -1 +1 @@
0.0.30 0.0.31

View File

@@ -8,8 +8,6 @@ plugins {
id("xyz.jpenilla.run-paper") id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow") id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper") id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
} }
runPaper.folia.registerTask() runPaper.folia.registerTask()
@@ -139,14 +137,6 @@ tasks {
} }
} }
tasks.publishAllPublicationsToHangar {
dependsOn("shadowJar")
}
tasks.modrinth {
dependsOn("shadowJar")
}
java { java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21)) toolchain.languageVersion.set(JavaLanguageVersion.of(21))
} }

View File

@@ -9,7 +9,8 @@
"1.21.7", "1.21.7",
"1.21.8", "1.21.8",
"1.21.9", "1.21.9",
"1.21.10" "1.21.10",
"1.21.11"
], ],
"channel": "RELEASE", "channel": "RELEASE",
"loaders": [ "loaders": [

View File

@@ -0,0 +1 @@
- Added support for 1.21.11

View File

@@ -8,33 +8,10 @@ plugins {
id("xyz.jpenilla.run-paper") id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow") id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper") id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
} }
runPaper.folia.registerTask() runPaper.folia.registerTask()
val supportedVersions =
listOf(
"1.19.4",
"1.20",
"1.20.1",
"1.20.2",
"1.20.3",
"1.20.4",
"1.20.5",
"1.20.6",
"1.21",
"1.21.1",
"1.21.2",
"1.21.3",
"1.21.4",
"1.21.5",
"1.21.6",
"1.21.7",
"1.21.8",
)
allprojects { allprojects {
group = "de.oliver" group = "de.oliver"
version = getFHVersion() version = getFHVersion()
@@ -167,14 +144,6 @@ tasks {
} }
} }
tasks.publishAllPublicationsToHangar {
dependsOn("shadowJar")
}
tasks.modrinth {
dependsOn("shadowJar")
}
java { java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21)) toolchain.languageVersion.set(JavaLanguageVersion.of(21))
} }
@@ -190,34 +159,3 @@ val gitCommitMessage: Provider<String> = providers.exec {
fun getFHVersion(): String { fun getFHVersion(): String {
return file("VERSION").readText() return file("VERSION").readText()
} }
hangarPublish {
publications.register("plugin") {
version = project.version as String
id = "FancyHolograms"
channel = "Alpha"
apiKey.set(System.getenv("HANGAR_PUBLISH_API_TOKEN"))
platforms {
paper {
jar = tasks.shadowJar.flatMap { it.archiveFile }
platformVersions = supportedVersions
}
}
changelog = gitCommitMessage.get()
}
}
modrinth {
token.set(System.getenv("MODRINTH_PUBLISH_API_TOKEN"))
projectId.set("fancyholograms")
versionNumber.set(getFHVersion())
versionType.set("alpha")
uploadFile.set(file("build/libs/${project.name}-${getFHVersion()}.jar"))
gameVersions.addAll(supportedVersions)
loaders.add("paper")
loaders.add("folia")
changelog.set(gitCommitMessage.get())
}

View File

@@ -23,7 +23,8 @@
"1.21.7", "1.21.7",
"1.21.8", "1.21.8",
"1.21.9", "1.21.9",
"1.21.10" "1.21.10",
"1.21.11"
], ],
"channel": "RELEASE", "channel": "RELEASE",
"loaders": [ "loaders": [

View File

@@ -292,7 +292,7 @@ public final class FancyHolograms extends JavaPlugin implements FancyHologramsPl
private void registerListeners() { private void registerListeners() {
getServer().getPluginManager().registerEvents(new PlayerListener(this), this); getServer().getPluginManager().registerEvents(new PlayerListener(this), this);
getServer().getPluginManager().registerEvents(new WorldListener(), this); getServer().getPluginManager().registerEvents(new WorldListener(), this);
if (Bukkit.getMinecraftVersion().equals("1.21.4") || Bukkit.getMinecraftVersion().equals("1.21.5") || Bukkit.getMinecraftVersion().equals("1.21.6") || Bukkit.getMinecraftVersion().equals("1.21.7") || Bukkit.getMinecraftVersion().equals("1.21.8")) { if (Set.of("1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8").contains(Bukkit.getMinecraftVersion())) {
getServer().getPluginManager().registerEvents(new PlayerLoadedListener(), this); getServer().getPluginManager().registerEvents(new PlayerLoadedListener(), this);
} }

View File

@@ -1 +1 @@
3.0.0-SNAPSHOT.9 3.0.0-SNAPSHOT.10

View File

@@ -8,27 +8,10 @@ plugins {
id("xyz.jpenilla.run-paper") id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow") id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper") id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
} }
runPaper.folia.registerTask() runPaper.folia.registerTask()
val supportedVersions =
listOf(
"1.20.5",
"1.20.6",
"1.21",
"1.21.1",
"1.21.2",
"1.21.3",
"1.21.4",
"1.21.5",
"1.21.6",
"1.21.7",
"1.21.8",
)
allprojects { allprojects {
group = "de.oliver" group = "de.oliver"
version = getFHVersion() version = getFHVersion()
@@ -162,14 +145,6 @@ tasks {
} }
} }
tasks.publishAllPublicationsToHangar {
dependsOn("shadowJar")
}
tasks.modrinth {
dependsOn("shadowJar")
}
java { java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21)) toolchain.languageVersion.set(JavaLanguageVersion.of(21))
} }
@@ -185,34 +160,3 @@ fun getLastCommitMessage(): String {
fun getFHVersion(): String { fun getFHVersion(): String {
return file("VERSION").readText() return file("VERSION").readText()
} }
hangarPublish {
publications.register("plugin") {
version = getFHVersion()
id = "FancyHolograms"
channel = "Alpha"
apiKey.set(System.getenv("HANGAR_PUBLISH_API_TOKEN"))
platforms {
paper {
jar = tasks.shadowJar.flatMap { it.archiveFile }
platformVersions = supportedVersions
}
}
changelog = getLastCommitMessage()
}
}
modrinth {
token.set(System.getenv("MODRINTH_PUBLISH_API_TOKEN"))
projectId.set("fancyholograms")
versionNumber.set(getFHVersion())
versionType.set("alpha")
uploadFile.set(file("build/libs/FancyHolograms-${getFHVersion()}.jar"))
gameVersions.addAll(supportedVersions)
loaders.add("paper")
loaders.add("folia")
changelog.set(getLastCommitMessage())
}

View File

@@ -17,7 +17,8 @@
"1.21.7", "1.21.7",
"1.21.8", "1.21.8",
"1.21.9", "1.21.9",
"1.21.10" "1.21.10",
"1.21.11"
], ],
"channel": "RELEASE", "channel": "RELEASE",
"loaders": [ "loaders": [

View File

@@ -311,7 +311,7 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog
getServer().getPluginManager().registerEvents(new PlayerListener(this), this); getServer().getPluginManager().registerEvents(new PlayerListener(this), this);
getServer().getPluginManager().registerEvents(new WorldLoadedListener(), this); getServer().getPluginManager().registerEvents(new WorldLoadedListener(), this);
if (Bukkit.getMinecraftVersion().equals("1.21.4") || Bukkit.getMinecraftVersion().equals("1.21.5") || Bukkit.getMinecraftVersion().equals("1.21.6")) { if (Set.of("1.21.4", "1.21.5", "1.21.6").contains(Bukkit.getMinecraftVersion())) {
getServer().getPluginManager().registerEvents(new PlayerLoadedListener(), this); getServer().getPluginManager().registerEvents(new PlayerLoadedListener(), this);
} }

View File

@@ -0,0 +1,6 @@
- Added support for 1.21.11
- Fixed skin mirroring for 1.21.9
- Added inverted permission check for `need_permission` action (use prefix `!` to invert)
- Added `/npc rotate <npc> <yaw> <pitch>` command to set NPC orientation
- Added `swing_arm_on_update` config option
- Added `use-minecraft-usercache` feature flag

View File

@@ -35,7 +35,7 @@ Check out **[images section](#images)** down below.
## Installation ## Installation
Paper **1.19.4** - **1.21.8** with **Java 21** (or higher) is required. Plugin should also work on **Paper** forks. Paper **1.19.4** - **1.21.11** with **Java 21** (or higher) is required. Plugin should also work on **Paper** forks.
**Spigot** is **not** supported. **Spigot** is **not** supported.

View File

@@ -1 +1 @@
2.8.0.306 2.8.0.307

View File

@@ -6,35 +6,10 @@ plugins {
id("xyz.jpenilla.run-paper") id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow") id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper") id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
} }
runPaper.folia.registerTask() runPaper.folia.registerTask()
val supportedVersions =
listOf(
"1.19.4",
"1.20",
"1.20.1",
"1.20.2",
"1.20.3",
"1.20.4",
"1.20.5",
"1.20.6",
"1.21",
"1.21.1",
"1.21.2",
"1.21.3",
"1.21.4",
"1.21.5",
"1.21.6",
"1.21.7",
"1.21.8",
"1.21.9",
"1.21.10"
)
allprojects { allprojects {
group = "de.oliver" group = "de.oliver"
version = getFNVersion() version = getFNVersion()
@@ -56,6 +31,7 @@ dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
implementation(project(":plugins:fancynpcs:fn-api")) implementation(project(":plugins:fancynpcs:fn-api"))
implementation(project(":plugins:fancynpcs:implementation_1_21_11"))
implementation(project(":plugins:fancynpcs:implementation_1_21_9")) implementation(project(":plugins:fancynpcs:implementation_1_21_9"))
implementation(project(":plugins:fancynpcs:implementation_1_21_6")) implementation(project(":plugins:fancynpcs:implementation_1_21_6"))
implementation(project(":plugins:fancynpcs:implementation_1_21_5")) implementation(project(":plugins:fancynpcs:implementation_1_21_5"))
@@ -204,14 +180,6 @@ tasks {
} }
} }
tasks.publishAllPublicationsToHangar {
dependsOn(":plugins:fancynpcs:shadowJar")
}
tasks.modrinth {
dependsOn(":plugins:fancynpcs:shadowJar")
}
java { java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21)) toolchain.languageVersion.set(JavaLanguageVersion.of(21))
} }
@@ -227,34 +195,3 @@ val gitCommitMessage: Provider<String> = providers.exec {
fun getFNVersion(): String { fun getFNVersion(): String {
return file("VERSION").readText() return file("VERSION").readText()
} }
hangarPublish {
publications.register("plugin") {
version = getFNVersion()
id = "FancyNpcs"
channel = "Alpha"
apiKey.set(System.getenv("HANGAR_PUBLISH_API_TOKEN"))
platforms {
paper {
jar = tasks.shadowJar.flatMap { it.archiveFile }
platformVersions.set(supportedVersions)
}
}
changelog = gitCommitMessage.get()
}
}
modrinth {
token.set(System.getenv("MODRINTH_PUBLISH_API_TOKEN"))
projectId.set("fancynpcs")
versionNumber.set(getFNVersion())
versionType.set("alpha")
uploadFile.set(file("build/libs/${project.name}-${getFNVersion()}.jar"))
gameVersions.addAll(supportedVersions)
loaders.add("paper")
loaders.add("folia")
changelog.set(gitCommitMessage.get())
}

View File

@@ -20,7 +20,13 @@ public class NeedPermissionAction extends NpcAction {
return; return;
} }
if (!context.getPlayer().hasPermission(value)) { boolean invertCheck = value.startsWith("!");
String permission = invertCheck ? value.substring(1) : value;
boolean hasPermission = context.getPlayer().hasPermission(permission);
boolean passesCheck = invertCheck ? !hasPermission : hasPermission;
if (!passesCheck) {
FancyNpcsPlugin.get().getTranslator().translate("action_missing_permissions").send(context.getPlayer()); FancyNpcsPlugin.get().getTranslator().translate("action_missing_permissions").send(context.getPlayer());
context.terminate(); context.terminate();
} }

View File

@@ -90,6 +90,7 @@ public class NpcModifyEvent extends Event implements Cancellable {
LOCATION, LOCATION,
MIRROR_SKIN, MIRROR_SKIN,
PLAYER_COMMAND, PLAYER_COMMAND,
ROTATION,
SERVER_COMMAND, SERVER_COMMAND,
SHOW_IN_TAB, SHOW_IN_TAB,
SKIN, SKIN,

View File

@@ -0,0 +1,27 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
paperweight.reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION
dependencies {
paperweight.paperDevBundle("25w45a-R0.1-SNAPSHOT")
// compileOnly("com.fancyinnovations:fancymc:1.21.6-pre2")
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly(project(":libraries:common"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.3")
}
tasks {
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release = 21
}
}

View File

@@ -0,0 +1,31 @@
package de.oliver.fancynpcs.v1_21_11;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerPlayer;
import java.util.function.Predicate;
public class FakeSynchronizer implements ServerEntity.Synchronizer {
public static final FakeSynchronizer INSTANCE = new FakeSynchronizer();
private FakeSynchronizer() {
}
@Override
public void sendToTrackingPlayers(Packet<? super ClientGamePacketListener> packet) {
}
@Override
public void sendToTrackingPlayersAndSelf(Packet<? super ClientGamePacketListener> packet) {
}
@Override
public void sendToTrackingPlayersFiltered(Packet<? super ClientGamePacketListener> packet, Predicate<ServerPlayer> predicate) {
}
}

View File

@@ -0,0 +1,459 @@
package de.oliver.fancynpcs.v1_21_11;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.datafixers.util.Pair;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.FancyNpcsPlugin;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.api.NpcData;
import de.oliver.fancynpcs.api.events.NpcSpawnEvent;
import de.oliver.fancynpcs.api.utils.NpcEquipmentSlot;
import io.papermc.paper.adventure.PaperAdventure;
import net.minecraft.Optionull;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.RemoteChatSession;
import net.minecraft.network.protocol.game.*;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ClientInformation;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.Team;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.entity.Player;
import org.lushplugins.chatcolorhandler.ModernChatColorHandler;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class Npc_1_21_11 extends Npc {
private final String localName;
private final UUID uuid;
private Entity npc;
private Display.TextDisplay sittingVehicle;
public Npc_1_21_11(NpcData data) {
super(data);
this.localName = generateLocalName();
this.uuid = UUID.randomUUID();
}
@Override
public void create() {
MinecraftServer minecraftServer = ((CraftServer) Bukkit.getServer()).getServer();
ServerLevel serverLevel = ((CraftWorld) data.getLocation().getWorld()).getHandle();
GameProfile gameProfile = new GameProfile(uuid, localName);
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""), ClientInformation.createDefault());
((ServerPlayer) npc).gameProfile = gameProfile;
} else {
Optional<Holder.Reference<EntityType<?>>> entityTypeReference = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType<?> nmsType = entityTypeReference.get().value(); // TODO handle empty
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, "factory"); // EntityType.factory
npc = factory.create(nmsType, serverLevel);
isTeamCreated.clear();
}
}
@Override
public void spawn(Player player) {
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
if (npc == null) {
return;
}
if (!data.getLocation().getWorld().getName().equalsIgnoreCase(serverPlayer.level().getWorld().getName())) {
return;
}
if (data.getSkinData() != null && data.getSkinData().hasTexture()) {
String value = data.getSkinData().getTextureValue();
String signature = data.getSkinData().getTextureSignature();
PropertyMap propertyMap = new PropertyMap(
ImmutableMultimap.of(
"textures",
new Property("textures", value, signature)
)
);
((ServerPlayer) npc).gameProfile = new GameProfile(uuid, localName, propertyMap);
}
NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
return;
}
if (npc instanceof ServerPlayer npcPlayer) {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = EnumSet.noneOf(ClientboundPlayerInfoUpdatePacket.Action.class);
actions.add(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER);
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
if (data.isShowInTab()) {
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
}
ClientboundPlayerInfoUpdatePacket playerInfoPacket = new ClientboundPlayerInfoUpdatePacket(actions, getEntry(npcPlayer, serverPlayer));
serverPlayer.connection.send(playerInfoPacket);
if (data.isSpawnEntity()) {
npc.setPos(data.getLocation().x(), data.getLocation().y(), data.getLocation().z());
}
}
ClientboundAddEntityPacket addEntityPacket = new ClientboundAddEntityPacket(
npc.getId(),
npc.getUUID(),
data.getLocation().x(),
data.getLocation().y(),
data.getLocation().z(),
data.getLocation().getPitch(),
data.getLocation().getYaw(),
npc.getType(),
0,
Vec3.ZERO,
data.getLocation().getYaw()
);
serverPlayer.connection.send(addEntityPacket);
isVisibleForPlayer.put(player.getUniqueId(), true);
int removeNpcsFromPlayerlistDelay = FancyNpcsPlugin.get().getFancyNpcConfig().getRemoveNpcsFromPlayerlistDelay();
if (!data.isShowInTab() && removeNpcsFromPlayerlistDelay > 0) {
FancyNpcsPlugin.get().getNpcThread().schedule(() -> {
ClientboundPlayerInfoRemovePacket playerInfoRemovePacket = new ClientboundPlayerInfoRemovePacket(List.of(npc.getUUID()));
serverPlayer.connection.send(playerInfoRemovePacket);
}, removeNpcsFromPlayerlistDelay, TimeUnit.MILLISECONDS);
}
update(player);
}
@Override
public void remove(Player player) {
if (npc == null) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
if (npc instanceof ServerPlayer npcPlayer) {
ClientboundPlayerInfoRemovePacket playerInfoRemovePacket = new ClientboundPlayerInfoRemovePacket(List.of((npcPlayer.getUUID())));
serverPlayer.connection.send(playerInfoRemovePacket);
}
// remove entity
ClientboundRemoveEntitiesPacket removeEntitiesPacket = new ClientboundRemoveEntitiesPacket(npc.getId());
serverPlayer.connection.send(removeEntitiesPacket);
// remove sitting vehicle
if (sittingVehicle != null) {
ClientboundRemoveEntitiesPacket removeSittingVehiclePacket = new ClientboundRemoveEntitiesPacket(sittingVehicle.getId());
serverPlayer.connection.send(removeSittingVehiclePacket);
}
isVisibleForPlayer.put(serverPlayer.getUUID(), false);
}
@Override
public void lookAt(Player player, Location location) {
if (npc == null) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
npc.setRot(location.getYaw(), location.getPitch());
npc.setYHeadRot(location.getYaw());
npc.setXRot(location.getPitch());
npc.setYRot(location.getYaw());
ClientboundTeleportEntityPacket teleportEntityPacket = new ClientboundTeleportEntityPacket(
npc.getId(),
new PositionMoveRotation(
new Vec3(data.getLocation().getX(), data.getLocation().getY(), data.getLocation().getZ()),
Vec3.ZERO,
location.getYaw(),
location.getPitch()
),
Set.of(),
false
);
serverPlayer.connection.send(teleportEntityPacket);
float angelMultiplier = 256f / 360f;
ClientboundRotateHeadPacket rotateHeadPacket = new ClientboundRotateHeadPacket(npc, (byte) (location.getYaw() * angelMultiplier));
serverPlayer.connection.send(rotateHeadPacket);
}
@Override
public void update(Player player, boolean swingArm) {
if (npc == null) {
return;
}
if (!isVisibleForPlayer.getOrDefault(player.getUniqueId(), false)) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
PlayerTeam team = new PlayerTeam(new Scoreboard(), "npc-" + localName);
team.getPlayers().clear();
team.getPlayers().add(npc instanceof ServerPlayer npcPlayer ? npcPlayer.getGameProfile().name() : npc.getStringUUID());
team.setColor(PaperAdventure.asVanilla(data.getGlowingColor()));
if (!data.isCollidable()) {
team.setCollisionRule(Team.CollisionRule.NEVER);
}
net.kyori.adventure.text.Component displayName = ModernChatColorHandler.translate(data.getDisplayName(), serverPlayer.getBukkitEntity());
Component vanillaComponent = PaperAdventure.asVanilla(displayName);
if (!(npc instanceof ServerPlayer)) {
npc.setCustomName(vanillaComponent);
npc.setCustomNameVisible(true);
} else {
npc.setCustomName(null);
npc.setCustomNameVisible(false);
}
if (data.getDisplayName().equalsIgnoreCase("<empty>")) {
team.setNameTagVisibility(Team.Visibility.NEVER);
npc.setCustomName(null);
npc.setCustomNameVisible(false);
} else {
team.setNameTagVisibility(Team.Visibility.ALWAYS);
}
if (npc instanceof ServerPlayer npcPlayer) {
team.setPlayerPrefix(vanillaComponent);
npcPlayer.listName = vanillaComponent;
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions = EnumSet.noneOf(ClientboundPlayerInfoUpdatePacket.Action.class);
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
if (data.isShowInTab()) {
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
}
ClientboundPlayerInfoUpdatePacket playerInfoPacket = new ClientboundPlayerInfoUpdatePacket(actions, getEntry(npcPlayer, serverPlayer));
serverPlayer.connection.send(playerInfoPacket);
}
boolean isTeamCreatedForPlayer = this.isTeamCreated.getOrDefault(player.getUniqueId(), false);
serverPlayer.connection.send(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, !isTeamCreatedForPlayer));
isTeamCreated.put(player.getUniqueId(), true);
npc.setGlowingTag(data.isGlowing());
data.applyAllAttributes(this);
// Set equipment
List<Pair<EquipmentSlot, ItemStack>> equipmentList = new ArrayList<>();
if (data.getEquipment() != null) {
for (NpcEquipmentSlot slot : data.getEquipment().keySet()) {
equipmentList.add(new Pair<>(EquipmentSlot.byName(slot.toNmsName()), CraftItemStack.asNMSCopy(data.getEquipment().get(slot))));
}
}
// Set body slot (from happy ghast harness attribute)
if (npc instanceof LivingEntity livingEntity) {
ItemStack bodySlot = livingEntity.getItemBySlot(EquipmentSlot.BODY);
if (!bodySlot.isEmpty()) {
equipmentList.add(new Pair<>(EquipmentSlot.BODY, bodySlot));
}
}
if (!equipmentList.isEmpty()) {
ClientboundSetEquipmentPacket setEquipmentPacket = new ClientboundSetEquipmentPacket(npc.getId(), equipmentList);
serverPlayer.connection.send(setEquipmentPacket);
}
if (npc instanceof ServerPlayer) {
// Enable second layer of skin (https://wiki.vg/Entity_metadata#Player)
npc.getEntityData().set(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION, (byte) (0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40));
}
refreshEntityData(player);
if (data.isSpawnEntity() && data.getLocation() != null) {
move(player, swingArm);
}
NpcAttribute playerPoseAttr = FancyNpcsPlugin.get().getAttributeManager().getAttributeByName(org.bukkit.entity.EntityType.PLAYER, "pose");
if (data.getAttributes().containsKey(playerPoseAttr)) {
String pose = data.getAttributes().get(playerPoseAttr);
if (pose.equals("sitting")) {
setSitting(serverPlayer);
} else {
if (sittingVehicle != null) {
ClientboundRemoveEntitiesPacket removeSittingVehiclePacket = new ClientboundRemoveEntitiesPacket(sittingVehicle.getId());
serverPlayer.connection.send(removeSittingVehiclePacket);
}
}
}
if (npc instanceof LivingEntity) {
Holder.Reference<Attribute> scaleAttribute = BuiltInRegistries.ATTRIBUTE.get(Identifier.parse("minecraft:scale")).get();
AttributeInstance attributeInstance = new AttributeInstance(scaleAttribute, (a) -> {
});
attributeInstance.setBaseValue(data.getScale());
ClientboundUpdateAttributesPacket updateAttributesPacket = new ClientboundUpdateAttributesPacket(npc.getId(), List.of(attributeInstance));
serverPlayer.connection.send(updateAttributesPacket);
}
}
@Override
protected void refreshEntityData(Player player) {
if (!isVisibleForPlayer.getOrDefault(player.getUniqueId(), false)) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
SynchedEntityData.DataItem<?>[] itemsById = (SynchedEntityData.DataItem<?>[]) ReflectionUtils.getValue(npc.getEntityData(), "itemsById"); // itemsById
List<SynchedEntityData.DataValue<?>> entityData = new ArrayList<>();
for (SynchedEntityData.DataItem<?> dataItem : itemsById) {
entityData.add(dataItem.value());
}
ClientboundSetEntityDataPacket setEntityDataPacket = new ClientboundSetEntityDataPacket(npc.getId(), entityData);
serverPlayer.connection.send(setEntityDataPacket);
}
public void move(Player player, boolean swingArm) {
if (npc == null) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
npc.setPosRaw(data.getLocation().x(), data.getLocation().y(), data.getLocation().z());
npc.setRot(data.getLocation().getYaw(), data.getLocation().getPitch());
npc.setYHeadRot(data.getLocation().getYaw());
npc.setXRot(data.getLocation().getPitch());
npc.setYRot(data.getLocation().getYaw());
ClientboundTeleportEntityPacket teleportEntityPacket = new ClientboundTeleportEntityPacket(
npc.getId(),
new PositionMoveRotation(
new Vec3(data.getLocation().getX(), data.getLocation().getY(), data.getLocation().getZ()),
Vec3.ZERO,
data.getLocation().getYaw(),
data.getLocation().getPitch()
),
Set.of(),
false
);
serverPlayer.connection.send(teleportEntityPacket);
float angelMultiplier = 256f / 360f;
ClientboundRotateHeadPacket rotateHeadPacket = new ClientboundRotateHeadPacket(npc, (byte) (data.getLocation().getYaw() * angelMultiplier));
serverPlayer.connection.send(rotateHeadPacket);
if (swingArm && npc instanceof ServerPlayer) {
ClientboundAnimatePacket animatePacket = new ClientboundAnimatePacket(npc, 0);
serverPlayer.connection.send(animatePacket);
}
}
private ClientboundPlayerInfoUpdatePacket.Entry getEntry(ServerPlayer npcPlayer, ServerPlayer viewer) {
GameProfile profile;
if (!data.isMirrorSkin()) {
profile = npcPlayer.getGameProfile();
} else {
Property textures = viewer.getGameProfile().properties().get("textures").iterator().next();
PropertyMap propertyMap = new PropertyMap(
ImmutableMultimap.of(
"textures",
new Property("textures", textures.value(), textures.signature())
)
);
profile = new GameProfile(uuid, localName, propertyMap);
}
return new ClientboundPlayerInfoUpdatePacket.Entry(
npcPlayer.getUUID(),
profile,
data.isShowInTab(),
0,
npcPlayer.gameMode.getGameModeForPlayer(),
npcPlayer.getTabListDisplayName(),
true,
-1,
Optionull.map(npcPlayer.getChatSession(), RemoteChatSession::asData)
);
}
public void setSitting(ServerPlayer serverPlayer) {
if (npc == null) {
return;
}
if (sittingVehicle == null) {
sittingVehicle = new Display.TextDisplay(EntityType.TEXT_DISPLAY, ((CraftWorld) data.getLocation().getWorld()).getHandle());
}
sittingVehicle.setPos(data.getLocation().x(), data.getLocation().y(), data.getLocation().z());
ServerEntity serverEntity = new ServerEntity(
serverPlayer.level(),
sittingVehicle,
0,
false,
FakeSynchronizer.INSTANCE,
Set.of()
);
ClientboundAddEntityPacket addEntityPacket = new ClientboundAddEntityPacket(sittingVehicle, serverEntity);
serverPlayer.connection.send(addEntityPacket);
sittingVehicle.passengers = ImmutableList.of(npc);
ClientboundSetPassengersPacket packet = new ClientboundSetPassengersPacket(sittingVehicle);
serverPlayer.connection.send(packet);
}
@Override
public float getEyeHeight() {
return npc.getEyeHeight();
}
@Override
public int getEntityId() {
return npc.getId();
}
public Entity getNpc() {
return npc;
}
}

View File

@@ -0,0 +1,13 @@
package de.oliver.fancynpcs.v1_21_11;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.Npc;
import net.minecraft.world.entity.Entity;
public class ReflectionHelper {
public static <T extends Entity> T getEntity(Npc npc) {
return (T) ReflectionUtils.getValue(npc, "npc");
}
}

View File

@@ -0,0 +1,38 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.AgeableMob;
import org.bukkit.entity.Ageable;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AgeableMobAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"baby",
List.of("true", "false"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && Ageable.class.isAssignableFrom(type.getEntityClass()))
.toList(),
AgeableMobAttributes::setBaby
));
return attributes;
}
private static void setBaby(Npc npc, String value) {
AgeableMob mob = ReflectionHelper.getEntity(npc);
boolean isBaby = Boolean.parseBoolean(value);
mob.setBaby(isBaby);
}
}

View File

@@ -0,0 +1,34 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.allay.Allay;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class AllayAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"dancing",
List.of("true", "false"),
List.of(EntityType.ALLAY),
AllayAttributes::setDancing
));
return attributes;
}
private static void setDancing(Npc npc, String value) {
Allay allay = ReflectionHelper.getEntity(npc);
boolean dancing = Boolean.parseBoolean(value);
allay.setDancing(dancing);
}
}

View File

@@ -0,0 +1,35 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.armadillo.Armadillo;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class ArmadilloAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"pose",
List.of("idle", "rolling", "unrolling", "scared"),
List.of(EntityType.ARMADILLO),
ArmadilloAttributes::setPose
));
return attributes;
}
private static void setPose(Npc npc, String value) {
Armadillo armadillo = ReflectionHelper.getEntity(npc);
Armadillo.ArmadilloState state = Armadillo.ArmadilloState.valueOf(value.toUpperCase());
armadillo.switchToState(state);
}
}

View File

@@ -0,0 +1,35 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class ArmorStandAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"show_arms",
List.of("true", "false"),
List.of(EntityType.ARMOR_STAND),
ArmorStandAttributes::setShowArms
));
return attributes;
}
private static void setShowArms(Npc npc, String value) {
ArmorStand armorStand = ReflectionHelper.getEntity(npc);
boolean showArms = Boolean.parseBoolean(value.toLowerCase());
armorStand.setShowArms(showArms);
}
}

View File

@@ -0,0 +1,56 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.NpcAttribute;
import java.util.ArrayList;
import java.util.List;
public class Attributes_1_21_11 {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.addAll(EntityAttributes.getAllAttributes());
attributes.addAll(LivingEntityAttributes.getAllAttributes());
attributes.addAll(AgeableMobAttributes.getAllAttributes());
attributes.addAll(IllagerAttributes.getAllAttributes());
attributes.addAll(SpellCasterAttributes.getAllAttributes());
attributes.addAll(PlayerAttributes.getAllAttributes());
attributes.addAll(SheepAttributes.getAllAttributes());
attributes.addAll(VillagerAttributes.getAllAttributes());
attributes.addAll(FrogAttributes.getAllAttributes());
attributes.addAll(HorseAttributes.getAllAttributes());
attributes.addAll(ParrotAttributes.getAllAttributes());
attributes.addAll(AxolotlAttributes.getAllAttributes());
attributes.addAll(TropicalFishAttributes.getAllAttributes());
attributes.addAll(FoxAttributes.getAllAttributes());
attributes.addAll(PandaAttributes.getAllAttributes());
attributes.addAll(GoatAttributes.getAllAttributes());
attributes.addAll(AllayAttributes.getAllAttributes());
attributes.addAll(CamelAttributes.getAllAttributes());
attributes.addAll(RabbitAttributes.getAllAttributes());
attributes.addAll(PiglinAttributes.getAllAttributes());
attributes.addAll(CatAttributes.getAllAttributes());
attributes.addAll(ShulkerAttributes.getAllAttributes());
attributes.addAll(WolfAttributes.getAllAttributes());
attributes.addAll(SlimeAttributes.getAllAttributes());
attributes.addAll(PigAttributes.getAllAttributes());
attributes.addAll(CowAttributes.getAllAttributes());
attributes.addAll(ChickenAttributes.getAllAttributes());
attributes.addAll(ArmorStandAttributes.getAllAttributes());
attributes.addAll(BeeAttributes.getAllAttributes());
attributes.addAll(VexAttributes.getAllAttributes());
attributes.addAll(ArmadilloAttributes.getAllAttributes());
attributes.addAll(HappyGhastAttributes.getAllAttributes());
attributes.addAll(SnifferAttributes.getAllAttributes());
attributes.addAll(DisplayAttributes.getAllAttributes());
attributes.addAll(TextDisplayAttributes.getAllAttributes());
attributes.addAll(BlockDisplayAttributes.getAllAttributes());
attributes.addAll(InteractionAttributes.getAllAttributes());
return attributes;
}
}

View File

@@ -0,0 +1,51 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.axolotl.Axolotl;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class AxolotlAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(Axolotl.Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.AXOLOTL),
AxolotlAttributes::setVariant
));
attributes.add(new NpcAttribute(
"playing_dead",
List.of("true", "false"),
List.of(EntityType.AXOLOTL),
AxolotlAttributes::setPlayingDead
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Axolotl axolotl = ReflectionHelper.getEntity(npc);
Axolotl.Variant variant = Axolotl.Variant.valueOf(value.toUpperCase());
axolotl.setVariant(variant);
}
private static void setPlayingDead(Npc npc, String value) {
Axolotl axolotl = ReflectionHelper.getEntity(npc);
boolean playingDead = Boolean.parseBoolean(value);
axolotl.setPlayingDead(playingDead);
}
}

View File

@@ -0,0 +1,84 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.Bee;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class BeeAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"angry",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setAngry
));
attributes.add(new NpcAttribute(
"sting",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setSting
));
attributes.add(new NpcAttribute(
"nectar",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setNectar
));
attributes.add(new NpcAttribute(
"rolling",
List.of("true", "false"),
List.of(EntityType.BEE),
BeeAttributes::setRolling
));
return attributes;
}
private static void setAngry(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setPersistentAngerEndTime(1);
case "false" -> bee.setPersistentAngerEndTime(0);
}
}
private static void setSting(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setHasStung(false);
case "false" -> bee.setHasStung(true);
}
}
private static void setNectar(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setHasNectar(true);
case "false" -> bee.setHasNectar(false);
}
}
private static void setRolling(Npc npc, String value) {
Bee bee = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> bee.setRolling(true);
case "false" -> bee.setRolling(false);
}
}
}

View File

@@ -0,0 +1,41 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.Display;
import net.minecraft.world.level.block.Block;
import org.bukkit.Material;
import org.bukkit.Registry;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class BlockDisplayAttributes {
private static final List<String> BLOCKS = Registry.MATERIAL.stream().filter(Material::isBlock).map(it -> it.key().value()).toList();
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"block",
BLOCKS,
List.of(EntityType.BLOCK_DISPLAY),
BlockDisplayAttributes::setBlock
));
return attributes;
}
private static void setBlock(Npc npc, String value) {
Display.BlockDisplay display = ReflectionHelper.getEntity(npc);
Block block = BuiltInRegistries.BLOCK.getValue(Identifier.parse(value.toLowerCase()));
display.setBlockState(block.defaultBlockState());
}
}

View File

@@ -0,0 +1,54 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.FancyNpcsPlugin;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.animal.camel.Camel;
import org.bukkit.Bukkit;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class CamelAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sitting", "dashing"),
List.of(EntityType.CAMEL),
CamelAttributes::setPose
));
return attributes;
}
private static void setPose(Npc npc, String value) {
Camel camel = ReflectionHelper.getEntity(npc);
Bukkit.getScheduler().runTask(FancyNpcsPlugin.get().getPlugin(), () -> {
switch (value.toLowerCase()) {
case "standing" -> {
camel.setPose(Pose.STANDING);
camel.setDashing(false);
camel.resetLastPoseChangeTick(camel.level().getGameTime());
}
case "sitting" -> {
camel.setPose(Pose.SITTING);
camel.setDashing(false);
camel.resetLastPoseChangeTick(-camel.level().getGameTime());
}
case "dashing" -> {
camel.setPose(Pose.STANDING);
camel.setDashing(true);
camel.resetLastPoseChangeTick(camel.level().getGameTime());
}
}
});
}
}

View File

@@ -0,0 +1,107 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.animal.Cat;
import net.minecraft.world.entity.animal.CatVariant;
import net.minecraft.world.item.DyeColor;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class CatAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
getCatVariantRegistry()
.listElementIds()
.map(id -> id.identifier().getPath())
.toList(),
List.of(EntityType.CAT),
CatAttributes::setVariant
));
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sleeping", "sitting"),
List.of(EntityType.CAT),
CatAttributes::setPose
));
attributes.add(new NpcAttribute(
"collar_color",
List.of("RED", "BLUE", "YELLOW", "GREEN", "PURPLE", "ORANGE", "LIME", "MAGENTA", "BROWN", "WHITE", "GRAY", "LIGHT_GRAY", "LIGHT_BLUE", "BLACK", "CYAN", "PINK", "NONE"),
List.of(EntityType.CAT),
CatAttributes::setCollarColor
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
final Cat cat = ReflectionHelper.getEntity(npc);
Holder<CatVariant> variant = getCatVariantRegistry()
.get(ResourceKey.create(
Registries.CAT_VARIANT,
Identifier.withDefaultNamespace(value.toLowerCase())
))
.orElseThrow();
cat.setVariant(variant);
}
private static void setPose(Npc npc, String value) {
final Cat cat = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
cat.setInSittingPose(false, false);
cat.setLying(false);
}
case "sleeping" -> {
cat.setInSittingPose(false, false);
cat.setLying(true);
}
case "sitting" -> {
cat.setLying(false);
cat.setOrderedToSit(true);
cat.setInSittingPose(true, false);
}
}
}
private static HolderLookup.RegistryLookup<CatVariant> getCatVariantRegistry() {
return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.CAT_VARIANT);
}
private static void setCollarColor(Npc npc, String value) {
Cat cat = ReflectionHelper.getEntity(npc);
if (value.equalsIgnoreCase("none") || value.isEmpty()) {
// Reset to no collar
cat.setTame(false, false);
return;
}
try {
DyeColor color = DyeColor.valueOf(value.toUpperCase());
if (!cat.isTame()) {
cat.setTame(true, false);
}
cat.setCollarColor(color);
} catch (IllegalArgumentException e) {
System.out.println("Invalid cat collar color: " + value);
}
}
}

View File

@@ -0,0 +1,54 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.animal.Chicken;
import net.minecraft.world.entity.animal.ChickenVariant;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class ChickenAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
getChickenVariantRegistry()
.listElementIds()
.map(id -> id.identifier().getPath())
.toList(),
List.of(EntityType.CHICKEN),
ChickenAttributes::setVariant
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
final Chicken cow = ReflectionHelper.getEntity(npc);
Holder<ChickenVariant> variant = getChickenVariantRegistry()
.get(ResourceKey.create(
Registries.CHICKEN_VARIANT,
Identifier.withDefaultNamespace(value.toLowerCase())
))
.orElseThrow();
cow.setVariant(variant);
}
private static HolderLookup.RegistryLookup<ChickenVariant> getChickenVariantRegistry() {
return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.CHICKEN_VARIANT);
}
}

View File

@@ -0,0 +1,54 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.animal.Cow;
import net.minecraft.world.entity.animal.CowVariant;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class CowAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
getCowVariantRegistry()
.listElementIds()
.map(id -> id.identifier().getPath())
.toList(),
List.of(EntityType.COW),
CowAttributes::setVariant
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
final Cow cow = ReflectionHelper.getEntity(npc);
Holder<CowVariant> variant = getCowVariantRegistry()
.get(ResourceKey.create(
Registries.COW_VARIANT,
Identifier.withDefaultNamespace(value.toLowerCase())
))
.orElseThrow();
cow.setVariant(variant);
}
private static HolderLookup.RegistryLookup<CowVariant> getCowVariantRegistry() {
return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.COW_VARIANT);
}
}

View File

@@ -0,0 +1,37 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.Display;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class DisplayAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"billboard",
Arrays.stream(org.bukkit.entity.Display.Billboard.values())
.map(Enum::name)
.toList(),
List.of(EntityType.TEXT_DISPLAY, EntityType.BLOCK_DISPLAY, EntityType.ITEM_DISPLAY),
DisplayAttributes::setBillboard
));
return attributes;
}
private static void setBillboard(Npc npc, String value) {
Display display = ReflectionHelper.getEntity(npc);
Display.BillboardConstraints billboard = Display.BillboardConstraints.valueOf(value.toUpperCase());
display.setBillboardConstraints(billboard);
}
}

View File

@@ -0,0 +1,103 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.Entity;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class EntityAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"on_fire",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setOnFire
));
attributes.add(new NpcAttribute(
"invisible",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setInvisible
));
attributes.add(new NpcAttribute(
"silent",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setSilent
));
attributes.add(new NpcAttribute(
"shaking",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setShaking
));
attributes.add(new NpcAttribute(
"on_ground",
List.of("true", "false"),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setOnGround
));
/*attributes.add(new NpcAttribute(
"entity_pose",
Arrays.stream(Pose.values()).map(Enum::toString).toList(),
Arrays.stream(EntityType.values()).toList(),
EntityAttributes::setEntityPose
));*/
return attributes;
}
private static void setOnFire(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean onFire = Boolean.parseBoolean(value);
entity.setSharedFlagOnFire(onFire);
}
private static void setInvisible(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean invisible = Boolean.parseBoolean(value);
entity.setInvisible(invisible);
}
private static void setSilent(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean silent = Boolean.parseBoolean(value);
entity.setSilent(silent);
}
private static void setShaking(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean shaking = Boolean.parseBoolean(value);
entity.setTicksFrozen(shaking ? entity.getTicksRequiredToFreeze() : 0);
}
private static void setOnGround(Npc npc, String value) {
Entity entity = ReflectionHelper.getEntity(npc);
boolean onGround = Boolean.parseBoolean(value);
entity.setOnGround(onGround);
}
}

View File

@@ -0,0 +1,66 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.Fox;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class FoxAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"type",
Arrays.stream(Fox.Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.FOX),
FoxAttributes::setType
));
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sleeping", "sitting"),
List.of(EntityType.FOX),
FoxAttributes::setPose
));
return attributes;
}
private static void setType(Npc npc, String value) {
Fox fox = ReflectionHelper.getEntity(npc);
Fox.Variant type = Fox.Variant.valueOf(value.toUpperCase());
fox.setVariant(type);
}
private static void setPose(Npc npc, String value) {
Fox fox = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
fox.setIsCrouching(false);
fox.setSleeping(false);
fox.setSitting(false, false);
}
case "sleeping" -> {
fox.setSleeping(true);
fox.setSitting(false, false);
fox.setIsCrouching(false);
}
case "sitting" -> {
fox.setSitting(true, false);
fox.setSleeping(false);
fox.setIsCrouching(false);
}
}
}
}

View File

@@ -0,0 +1,53 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.animal.frog.Frog;
import net.minecraft.world.entity.animal.frog.FrogVariant;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class FrogAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
getFrogVariantRegistry()
.listElementIds()
.map(id -> id.identifier().getPath())
.toList(),
List.of(EntityType.FROG),
FrogAttributes::setVariant
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
final Frog frog = ReflectionHelper.getEntity(npc);
Holder<FrogVariant> variant = getFrogVariantRegistry()
.get(ResourceKey.create(
Registries.FROG_VARIANT,
Identifier.withDefaultNamespace(value.toLowerCase())
))
.orElseThrow();
frog.setVariant(variant);
}
private static HolderLookup.RegistryLookup<FrogVariant> getFrogVariantRegistry() {
return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.FROG_VARIANT);
}
}

View File

@@ -0,0 +1,44 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.goat.Goat;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class GoatAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"horns",
List.of("none", "left", "right", "both"),
List.of(EntityType.GOAT),
GoatAttributes::setHorns
));
return attributes;
}
private static void setHorns(Npc npc, String value) {
Goat goat = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "none" -> goat.removeHorns();
case "both" -> goat.addHorns();
case "left" -> {
goat.getEntityData().set(Goat.DATA_HAS_LEFT_HORN, true);
goat.getEntityData().set(Goat.DATA_HAS_RIGHT_HORN, false);
}
case "right" -> {
goat.getEntityData().set(Goat.DATA_HAS_RIGHT_HORN, true);
goat.getEntityData().set(Goat.DATA_HAS_LEFT_HORN, false);
}
}
}
}

View File

@@ -0,0 +1,57 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.HappyGhast;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class HappyGhastAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"harness",
List.of("white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"),
List.of(EntityType.HAPPY_GHAST),
HappyGhastAttributes::setHarness
));
return attributes;
}
private static void setHarness(Npc npc, String value) {
HappyGhast ghast = ReflectionHelper.getEntity(npc);
ItemStack harnessItem = switch (value.toLowerCase()) {
case "white" -> Items.WHITE_HARNESS.getDefaultInstance();
case "orange" -> Items.ORANGE_HARNESS.getDefaultInstance();
case "magenta" -> Items.MAGENTA_HARNESS.getDefaultInstance();
case "light_blue" -> Items.LIGHT_BLUE_HARNESS.getDefaultInstance();
case "yellow" -> Items.YELLOW_HARNESS.getDefaultInstance();
case "lime" -> Items.LIME_HARNESS.getDefaultInstance();
case "pink" -> Items.PINK_HARNESS.getDefaultInstance();
case "gray" -> Items.GRAY_HARNESS.getDefaultInstance();
case "light_gray" -> Items.LIGHT_GRAY_HARNESS.getDefaultInstance();
case "cyan" -> Items.CYAN_HARNESS.getDefaultInstance();
case "purple" -> Items.PURPLE_HARNESS.getDefaultInstance();
case "blue" -> Items.BLUE_HARNESS.getDefaultInstance();
case "brown" -> Items.BROWN_HARNESS.getDefaultInstance();
case "green" -> Items.GREEN_HARNESS.getDefaultInstance();
case "red" -> Items.RED_HARNESS.getDefaultInstance();
case "black" -> Items.BLACK_HARNESS.getDefaultInstance();
default -> Items.AIR.getDefaultInstance();
};
if (!harnessItem.isEmpty()) {
ghast.setItemSlot(EquipmentSlot.BODY, harnessItem);
}
}
}

View File

@@ -0,0 +1,84 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.horse.Horse;
import net.minecraft.world.entity.animal.horse.Markings;
import net.minecraft.world.entity.animal.horse.Variant;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class HorseAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.HORSE),
HorseAttributes::setVariant
));
attributes.add(new NpcAttribute(
"markings",
Arrays.stream(Markings.values())
.map(Enum::name)
.toList(),
List.of(EntityType.HORSE),
HorseAttributes::setMarkings
));
attributes.add(new NpcAttribute(
"pose",
List.of("eating", "rearing", "standing"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && (type == EntityType.HORSE || type == EntityType.DONKEY ||
type == EntityType.MULE || type == EntityType.SKELETON_HORSE || type == EntityType.ZOMBIE_HORSE))
.toList(),
HorseAttributes::setPose
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Horse horse = ReflectionHelper.getEntity(npc);
Variant variant = Variant.valueOf(value.toUpperCase());
horse.setVariantAndMarkings(variant, horse.getMarkings());
}
private static void setMarkings(Npc npc, String value) {
Horse horse = ReflectionHelper.getEntity(npc);
Markings markings = Markings.valueOf(value.toUpperCase());
horse.setVariantAndMarkings(horse.getVariant(), markings);
}
private static void setPose(Npc npc, String value) {
net.minecraft.world.entity.animal.horse.AbstractHorse horse = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
horse.setEating(false);
horse.setStanding(0);
}
case "rearing" -> {
horse.setStanding(20);
horse.setEating(false);
}
case "eating" -> {
horse.setStanding(0);
horse.setEating(true);
}
}
}
}

View File

@@ -0,0 +1,39 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.raid.Raider;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Illager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class IllagerAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"celebrating",
List.of("true", "false"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && Illager.class.isAssignableFrom(type.getEntityClass()))
.toList(),
IllagerAttributes::setCelebrating
));
return attributes;
}
private static void setCelebrating(Npc npc, String value) {
Raider raider = ReflectionHelper.getEntity(npc);
boolean isCelebrating = Boolean.parseBoolean(value);
raider.setCelebrating(isCelebrating);
}
}

View File

@@ -0,0 +1,60 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.Interaction;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class InteractionAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"height",
new ArrayList<>(),
List.of(EntityType.INTERACTION),
InteractionAttributes::setHeight
));
attributes.add(new NpcAttribute(
"width",
new ArrayList<>(),
List.of(EntityType.INTERACTION),
InteractionAttributes::setWidth
));
return attributes;
}
private static void setHeight(Npc npc, String value) {
Interaction interaction = ReflectionHelper.getEntity(npc);
float height;
try {
height = Float.parseFloat(value);
} catch (NumberFormatException e) {
return;
}
interaction.setHeight(height);
}
private static void setWidth(Npc npc, String value) {
Interaction interaction = ReflectionHelper.getEntity(npc);
float width;
try {
width = Float.parseFloat(value);
} catch (NumberFormatException e) {
return;
}
interaction.setWidth(width);
}
}

View File

@@ -0,0 +1,67 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.InteractionHand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LivingEntityAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
/*attributes.add(new NpcAttribute(
"hurt",
List.of("true", "false"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && LivingEntity.class.isAssignableFrom(type.getEntityClass()))
.toList(),
LivingEntityAttributes::setHurt
));*/
attributes.add(new NpcAttribute(
"use_item",
List.of("main_hand", "off_hand", "none"),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && LivingEntity.class.isAssignableFrom(type.getEntityClass()))
.toList(),
LivingEntityAttributes::setUseItem
));
return attributes;
}
private static void setHurt(Npc npc, String value) {
net.minecraft.world.entity.LivingEntity livingEntity = ReflectionHelper.getEntity(npc);
boolean isHurt = Boolean.parseBoolean(value);
if (isHurt) {
livingEntity.hurtDuration = 1;
livingEntity.hurtTime = 1;
livingEntity.hurtMarked = true;
livingEntity.animateHurt(0);
} else {
livingEntity.hurtDuration = 0;
livingEntity.hurtTime = 0;
livingEntity.hurtMarked = false;
}
}
private static void setUseItem(Npc npc, String value) {
net.minecraft.world.entity.LivingEntity livingEntity = ReflectionHelper.getEntity(npc);
switch (value.toUpperCase()) {
case "NONE" -> livingEntity.stopUsingItem();
case "MAIN_HAND" -> livingEntity.startUsingItem(InteractionHand.MAIN_HAND, true);
case "OFF_HAND" -> livingEntity.startUsingItem(InteractionHand.OFF_HAND, true);
}
}
}

View File

@@ -0,0 +1,101 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.entity.animal.Panda;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PandaAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"gene",
Arrays.stream(Panda.Gene.values())
.map(Enum::name)
.toList(),
List.of(EntityType.PANDA),
PandaAttributes::setGene
));
attributes.add(new NpcAttribute(
"eating",
List.of("true", "false"),
List.of(EntityType.PANDA),
PandaAttributes::setEating
));
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sitting", "onBack", "rolling"),
List.of(EntityType.PANDA),
PandaAttributes::setPose
));
return attributes;
}
private static void setGene(Npc npc, String value) {
Panda panda = ReflectionHelper.getEntity(npc);
Panda.Gene gene = Panda.Gene.valueOf(value.toUpperCase());
panda.setMainGene(gene);
}
private static void setPose(Npc npc, String value) {
Panda panda = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
setFlag(panda, 8, false); //sitting
panda.roll(false);
panda.setOnBack(false);
}
case "sitting" -> {
panda.roll(false);
panda.setOnBack(false);
setFlag(panda, 8, true); //sitting
}
case "onback" -> {
setFlag(panda, 8, false); //sitting
panda.roll(false);
panda.setOnBack(true);
}
case "rolling" -> {
setFlag(panda, 8, false); //sitting
panda.setOnBack(false);
panda.roll(true);
}
}
}
private static void setEating(Npc npc, String value) {
Panda panda = ReflectionHelper.getEntity(npc);
boolean eating = Boolean.parseBoolean(value);
panda.eat(eating);
}
private static void setFlag(Panda panda, int mask, boolean value) {
EntityDataAccessor<Byte> DATA_ID_FLAGS = (EntityDataAccessor<Byte>) ReflectionUtils.getValue(panda, "DATA_ID_FLAGS");
byte b0 = panda.getEntityData().get(DATA_ID_FLAGS);
if (value) {
panda.getEntityData().set(DATA_ID_FLAGS, (byte) (b0 | mask));
} else {
panda.getEntityData().set(DATA_ID_FLAGS, (byte) (b0 & ~mask));
}
}
}

View File

@@ -0,0 +1,59 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.Parrot;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ParrotAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(Parrot.Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.PARROT),
ParrotAttributes::setVariant
));
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sitting"),
List.of(EntityType.PARROT),
ParrotAttributes::setPose
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Parrot parrot = ReflectionHelper.getEntity(npc);
Parrot.Variant variant = Parrot.Variant.valueOf(value.toUpperCase());
parrot.setVariant(variant);
}
private static void setPose(Npc npc, String value) {
Parrot parrot = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> {
parrot.setOrderedToSit(false);
parrot.setInSittingPose(false, false);
}
case "sitting" -> {
parrot.setOrderedToSit(true);
parrot.setInSittingPose(true, false);
}
}
}
}

View File

@@ -0,0 +1,73 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.Pig;
import net.minecraft.world.entity.animal.PigVariant;
import net.minecraft.world.item.Items;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class PigAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
getPigVariantRegistry()
.listElementIds()
.map(id -> id.identifier().getPath())
.toList(),
List.of(EntityType.PIG),
PigAttributes::setVariant
));
attributes.add(new NpcAttribute(
"has_saddle",
List.of("true", "false"),
List.of(EntityType.PIG),
PigAttributes::setHasSaddle
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
final Pig pig = ReflectionHelper.getEntity(npc);
Holder<PigVariant> variant = getPigVariantRegistry()
.get(ResourceKey.create(
Registries.PIG_VARIANT,
Identifier.withDefaultNamespace(value.toLowerCase())
))
.orElseThrow();
pig.setVariant(variant);
}
private static void setHasSaddle(Npc npc, String value) {
Pig pig = ReflectionHelper.getEntity(npc);
boolean hasSaddle = Boolean.parseBoolean(value.toLowerCase());
if (hasSaddle) {
pig.setItemSlot(EquipmentSlot.SADDLE, Items.SADDLE.getDefaultInstance());
}
}
private static HolderLookup.RegistryLookup<PigVariant> getPigVariantRegistry() {
return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.PIG_VARIANT);
}
}

View File

@@ -0,0 +1,34 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.monster.piglin.Piglin;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class PiglinAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"dancing",
List.of("true", "false"),
List.of(EntityType.PIGLIN),
PiglinAttributes::setDancing
));
return attributes;
}
private static void setDancing(Npc npc, String value) {
Piglin piglin = ReflectionHelper.getEntity(npc);
boolean dancing = Boolean.parseBoolean(value);
piglin.setDancing(dancing);
}
}

View File

@@ -0,0 +1,40 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancylib.ReflectionUtils;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.entity.player.Player;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class PlayerAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "crouching", "sleeping", "swimming", "sitting"),
List.of(EntityType.PLAYER),
PlayerAttributes::setPose
));
return attributes;
}
private static void setPose(Npc npc, String value) {
Player player = ReflectionHelper.getEntity(npc);
Pose pose = Pose.valueOf(value.toUpperCase());
EntityDataAccessor<Pose> DATA_POSE = (EntityDataAccessor<Pose>) ReflectionUtils.getStaticValue(Entity.class, "DATA_POSE"); // DATA_POSE
player.getEntityData().set(DATA_POSE, pose);
}
}

View File

@@ -0,0 +1,37 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.Rabbit;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RabbitAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"variant",
Arrays.stream(Rabbit.Variant.values())
.map(Enum::name)
.toList(),
List.of(EntityType.RABBIT),
RabbitAttributes::setVariant
));
return attributes;
}
private static void setVariant(Npc npc, String value) {
Rabbit rabbit = ReflectionHelper.getEntity(npc);
Rabbit.Variant variant = Rabbit.Variant.valueOf(value.toUpperCase());
rabbit.setVariant(variant);
}
}

View File

@@ -0,0 +1,50 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.sheep.Sheep;
import net.minecraft.world.item.DyeColor;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SheepAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"wool_color",
Arrays.stream(DyeColor.values()).map(dyeColor -> dyeColor.name().toLowerCase()).toList(),
List.of(EntityType.SHEEP),
SheepAttributes::setColor
));
attributes.add(new NpcAttribute(
"sheared",
Arrays.asList("true", "false"),
List.of(EntityType.SHEEP),
SheepAttributes::setSheared
));
return attributes;
}
private static void setColor(Npc npc, String value) {
Sheep sheep = ReflectionHelper.getEntity(npc);
sheep.setColor(DyeColor.byName(value.toLowerCase(), DyeColor.WHITE));
}
private static void setSheared(Npc npc, String value) {
Sheep sheep = ReflectionHelper.getEntity(npc);
boolean sheared = Boolean.parseBoolean(value);
sheep.setSheared(sheared);
}
}

View File

@@ -0,0 +1,54 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.monster.Shulker;
import net.minecraft.world.item.DyeColor;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ShulkerAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"color",
Arrays.stream(DyeColor.values())
.map(Enum::name)
.toList(),
List.of(EntityType.SHULKER),
ShulkerAttributes::setColor
));
attributes.add(new NpcAttribute(
"shield",
List.of("open", "closed"),
List.of(EntityType.SHULKER),
ShulkerAttributes::setShield
));
return attributes;
}
private static void setColor(Npc npc, String value) {
Shulker shulker = ReflectionHelper.getEntity(npc);
DyeColor color = DyeColor.byName(value.toLowerCase(), DyeColor.PURPLE);
shulker.getEntityData().set(Shulker.DATA_COLOR_ID, (byte) color.getId());
}
private static void setShield(Npc npc, String value) {
Shulker shulker = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "closed" -> shulker.setRawPeekAmount(0);
case "open" -> shulker.setRawPeekAmount(Byte.MAX_VALUE);
}
}
}

View File

@@ -0,0 +1,40 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.monster.Slime;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class SlimeAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"size",
new ArrayList<>(),
List.of(EntityType.SLIME),
SlimeAttributes::setSize
));
return attributes;
}
private static void setSize(Npc npc, String value) {
Slime slime = ReflectionHelper.getEntity(npc);
int size;
try {
size = Integer.parseInt(value);
} catch (NumberFormatException e) {
return;
}
slime.setSize(size, false);
}
}

View File

@@ -0,0 +1,36 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.sniffer.Sniffer;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SnifferAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"state",
Arrays.stream(Sniffer.State.values())
.map(Enum::name)
.toList(),
List.of(EntityType.SNIFFER),
SnifferAttributes::setState
));
return attributes;
}
private static void setState(Npc npc, String value) {
final Sniffer sniffer = ReflectionHelper.getEntity(npc);
Sniffer.State state = Sniffer.State.valueOf(value.toUpperCase());
sniffer.transitionTo(state);
}
}

View File

@@ -0,0 +1,39 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.monster.SpellcasterIllager;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Spellcaster;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SpellCasterAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"casting",
Arrays.stream(SpellcasterIllager.IllagerSpell.values()).map(Enum::toString).toList(),
Arrays.stream(EntityType.values())
.filter(type -> type.getEntityClass() != null && Spellcaster.class.isAssignableFrom(type.getEntityClass()))
.toList(),
SpellCasterAttributes::setPose
));
return attributes;
}
private static void setPose(Npc npc, String value) {
SpellcasterIllager spellcasterIllager = ReflectionHelper.getEntity(npc);
SpellcasterIllager.IllagerSpell spell = SpellcasterIllager.IllagerSpell.valueOf(value);
spellcasterIllager.setIsCastingSpell(spell);
}
}

View File

@@ -0,0 +1,36 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.minecraft.world.entity.Display;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class TextDisplayAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"text",
new ArrayList<>(),
List.of(EntityType.TEXT_DISPLAY),
TextDisplayAttributes::setText
));
return attributes;
}
private static void setText(Npc npc, String value) {
Display.TextDisplay display = ReflectionHelper.getEntity(npc);
Component text = MiniMessage.miniMessage().deserialize(value);
display.setText(PaperAdventure.asVanilla(text));
}
}

View File

@@ -0,0 +1,72 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.animal.TropicalFish;
import net.minecraft.world.item.DyeColor;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TropicalFishAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"pattern",
Arrays.stream(TropicalFish.Pattern.values())
.map(Enum::name)
.toList(),
List.of(EntityType.TROPICAL_FISH),
TropicalFishAttributes::setPattern
));
attributes.add(new NpcAttribute(
"base_color",
Arrays.stream(DyeColor.values())
.map(Enum::name)
.toList(),
List.of(EntityType.TROPICAL_FISH),
TropicalFishAttributes::setBaseColor
));
attributes.add(new NpcAttribute(
"pattern_color",
Arrays.stream(DyeColor.values())
.map(Enum::name)
.toList(),
List.of(EntityType.TROPICAL_FISH),
TropicalFishAttributes::setPatternColor
));
return attributes;
}
private static void setPattern(Npc npc, String value) {
TropicalFish tropicalFish = ReflectionHelper.getEntity(npc);
TropicalFish.Pattern pattern = TropicalFish.Pattern.valueOf(value.toUpperCase());
tropicalFish.setPackedVariant(pattern.getPackedId());
}
private static void setBaseColor(Npc npc, String value) {
TropicalFish tropicalFish = ReflectionHelper.getEntity(npc);
DyeColor color = DyeColor.byName(value.toLowerCase(), DyeColor.WHITE);
TropicalFish.Variant variant = new TropicalFish.Variant(tropicalFish.getPattern(), color, tropicalFish.getPatternColor());
tropicalFish.setPackedVariant(variant.getPackedId());
}
private static void setPatternColor(Npc npc, String value) {
TropicalFish tropicalFish = ReflectionHelper.getEntity(npc);
DyeColor color = DyeColor.byName(value.toLowerCase(), DyeColor.WHITE);
TropicalFish.Variant variant = new TropicalFish.Variant(tropicalFish.getPattern(), tropicalFish.getBaseColor(), color);
tropicalFish.setPackedVariant(variant.getPackedId());
}
}

View File

@@ -0,0 +1,36 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.world.entity.monster.Vex;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class VexAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"charging",
List.of("true", "false"),
List.of(EntityType.VEX),
VexAttributes::setCharging
));
return attributes;
}
private static void setCharging(Npc npc, String value) {
Vex vex = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "true" -> vex.setIsCharging(true);
case "false" -> vex.setIsCharging(false);
}
}
}

View File

@@ -0,0 +1,55 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerType;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class VillagerAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"profession",
BuiltInRegistries.VILLAGER_PROFESSION.keySet().stream().map(Identifier::getPath).toList(),
List.of(EntityType.VILLAGER),
VillagerAttributes::setProfession
));
attributes.add(new NpcAttribute(
"type",
BuiltInRegistries.VILLAGER_TYPE.keySet().stream().map(Identifier::getPath).toList(),
List.of(EntityType.VILLAGER),
VillagerAttributes::setType
));
return attributes;
}
private static void setProfession(Npc npc, String value) {
Villager villager = ReflectionHelper.getEntity(npc);
Holder<VillagerProfession> profession = BuiltInRegistries.VILLAGER_PROFESSION.get(Identifier.tryParse(value)).orElseThrow();
villager.setVillagerData(villager.getVillagerData().withProfession(profession));
}
private static void setType(Npc npc, String value) {
Villager villager = ReflectionHelper.getEntity(npc);
Holder<VillagerType> type = BuiltInRegistries.VILLAGER_TYPE.get(Identifier.tryParse(value)).orElseThrow();
villager.setVillagerData(villager.getVillagerData().withType(type));
}
}

View File

@@ -0,0 +1,127 @@
package de.oliver.fancynpcs.v1_21_11.attributes;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.NpcAttribute;
import de.oliver.fancynpcs.v1_21_11.ReflectionHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.animal.wolf.Wolf;
import net.minecraft.world.entity.animal.wolf.WolfVariant;
import net.minecraft.world.item.DyeColor;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class WolfAttributes {
public static List<NpcAttribute> getAllAttributes() {
List<NpcAttribute> attributes = new ArrayList<>();
attributes.add(new NpcAttribute(
"pose",
List.of("standing", "sitting"),
List.of(EntityType.WOLF),
WolfAttributes::setPose
));
attributes.add(new NpcAttribute(
"angry",
List.of("true", "false"),
List.of(EntityType.WOLF),
WolfAttributes::setAngry
));
attributes.add(new NpcAttribute(
"variant",
getWolfVariantRegistry()
.listElementIds()
.map(id -> id.identifier().getPath())
.toList(),
List.of(EntityType.WOLF),
WolfAttributes::setVariant
));
attributes.add(new NpcAttribute(
"collar_color",
List.of("RED", "BLUE", "YELLOW", "GREEN", "PURPLE", "ORANGE", "LIME", "MAGENTA", "BROWN", "WHITE", "GRAY", "LIGHT_GRAY", "LIGHT_BLUE", "BLACK", "CYAN", "PINK", "NONE"),
List.of(EntityType.WOLF),
WolfAttributes::setCollarColor
));
return attributes;
}
private static void setPose(Npc npc, String value) {
Wolf wolf = ReflectionHelper.getEntity(npc);
switch (value.toLowerCase()) {
case "standing" -> wolf.setInSittingPose(false, false);
case "sitting" -> wolf.setInSittingPose(true, false);
}
}
private static void setAngry(Npc npc, String value) {
Wolf wolf = ReflectionHelper.getEntity(npc);
boolean angry = Boolean.parseBoolean(value.toLowerCase());
wolf.setTimeToRemainAngry(angry ? 100 : 0);
}
private static void setVariant(Npc npc, String value) {
Wolf wolf = ReflectionHelper.getEntity(npc);
Registry<WolfVariant> registry = wolf.level().registryAccess().lookupOrThrow(Registries.WOLF_VARIANT);
Identifier variantLocation = Identifier.tryParse("minecraft:" + value.toLowerCase());
if (variantLocation == null) {
System.out.println("Invalid variant name: " + value);
return;
}
WolfVariant variant = registry.getOptional(variantLocation).orElse(null);
if (variant == null) {
System.out.println("Wolf variant not found: " + variantLocation);
return;
}
// Get the ResourceKey from the registry
registry.getResourceKey(variant).ifPresentOrElse(
key -> {
// Get the holder from the registry — this is properly bound
Holder<WolfVariant> holder = registry.wrapAsHolder(variant);
wolf.setVariant(holder);
},
() -> System.out.println("Wolf variant not registered: " + variantLocation)
);
}
private static void setCollarColor(Npc npc, String value) {
Wolf wolf = ReflectionHelper.getEntity(npc);
if (value.equalsIgnoreCase("none") || value.isEmpty()) {
// Reset to no collar
wolf.setTame(false, false);
return;
}
try {
DyeColor color = DyeColor.valueOf(value.toUpperCase());
if (!wolf.isTame()) {
wolf.setTame(true, false);
}
wolf.setCollarColor(color);
} catch (IllegalArgumentException e) {
System.out.println("Invalid wolf collar color: " + value);
}
}
private static HolderLookup.RegistryLookup<WolfVariant> getWolfVariantRegistry() {
return MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.WOLF_VARIANT);
}
}

View File

@@ -23,7 +23,8 @@
"1.21.7", "1.21.7",
"1.21.8", "1.21.8",
"1.21.9", "1.21.9",
"1.21.10" "1.21.10",
"1.21.11"
], ],
"channel": "RELEASE", "channel": "RELEASE",
"loaders": [ "loaders": [

View File

@@ -8,6 +8,7 @@ import de.oliver.fancynpcs.v1_20_2.attributes.Attributes_1_20_2;
import de.oliver.fancynpcs.v1_20_4.attributes.Attributes_1_20_4; import de.oliver.fancynpcs.v1_20_4.attributes.Attributes_1_20_4;
import de.oliver.fancynpcs.v1_20_6.attributes.Attributes_1_20_5; import de.oliver.fancynpcs.v1_20_6.attributes.Attributes_1_20_5;
import de.oliver.fancynpcs.v1_21_1.attributes.Attributes_1_21_1; import de.oliver.fancynpcs.v1_21_1.attributes.Attributes_1_21_1;
import de.oliver.fancynpcs.v1_21_11.attributes.Attributes_1_21_11;
import de.oliver.fancynpcs.v1_21_3.attributes.Attributes_1_21_3; import de.oliver.fancynpcs.v1_21_3.attributes.Attributes_1_21_3;
import de.oliver.fancynpcs.v1_21_4.attributes.Attributes_1_21_4; import de.oliver.fancynpcs.v1_21_4.attributes.Attributes_1_21_4;
import de.oliver.fancynpcs.v1_21_5.attributes.Attributes_1_21_5; import de.oliver.fancynpcs.v1_21_5.attributes.Attributes_1_21_5;
@@ -31,6 +32,7 @@ public class AttributeManagerImpl implements AttributeManager {
private void init() { private void init() {
String mcVersion = Bukkit.getMinecraftVersion(); String mcVersion = Bukkit.getMinecraftVersion();
switch (mcVersion) { switch (mcVersion) {
case "1.21.11" -> attributes = Attributes_1_21_11.getAllAttributes();
case "1.21.9", "1.21.10" -> attributes = Attributes_1_21_9.getAllAttributes(); case "1.21.9", "1.21.10" -> attributes = Attributes_1_21_9.getAllAttributes();
case "1.21.6", "1.21.7", "1.21.8" -> attributes = Attributes_1_21_6.getAllAttributes(); case "1.21.6", "1.21.7", "1.21.8" -> attributes = Attributes_1_21_6.getAllAttributes();
case "1.21.5" -> attributes = Attributes_1_21_5.getAllAttributes(); case "1.21.5" -> attributes = Attributes_1_21_5.getAllAttributes();

View File

@@ -53,6 +53,7 @@ import de.oliver.fancynpcs.v1_20_2.Npc_1_20_2;
import de.oliver.fancynpcs.v1_20_4.Npc_1_20_4; import de.oliver.fancynpcs.v1_20_4.Npc_1_20_4;
import de.oliver.fancynpcs.v1_20_6.Npc_1_20_6; import de.oliver.fancynpcs.v1_20_6.Npc_1_20_6;
import de.oliver.fancynpcs.v1_21_1.Npc_1_21_1; import de.oliver.fancynpcs.v1_21_1.Npc_1_21_1;
import de.oliver.fancynpcs.v1_21_11.Npc_1_21_11;
import de.oliver.fancynpcs.v1_21_3.Npc_1_21_3; import de.oliver.fancynpcs.v1_21_3.Npc_1_21_3;
import de.oliver.fancynpcs.v1_21_4.Npc_1_21_4; import de.oliver.fancynpcs.v1_21_4.Npc_1_21_4;
import de.oliver.fancynpcs.v1_21_5.Npc_1_21_5; import de.oliver.fancynpcs.v1_21_5.Npc_1_21_5;
@@ -162,6 +163,7 @@ public class FancyNpcs extends JavaPlugin implements FancyNpcsPlugin {
String mcVersion = Bukkit.getMinecraftVersion(); String mcVersion = Bukkit.getMinecraftVersion();
switch (mcVersion) { switch (mcVersion) {
case "1.21.11" -> npcAdapter = Npc_1_21_11::new;
case "1.21.9", "1.21.10" -> npcAdapter = Npc_1_21_9::new; case "1.21.9", "1.21.10" -> npcAdapter = Npc_1_21_9::new;
case "1.21.6", "1.21.7", "1.21.8" -> npcAdapter = Npc_1_21_6::new; case "1.21.6", "1.21.7", "1.21.8" -> npcAdapter = Npc_1_21_6::new;
case "1.21.5" -> npcAdapter = Npc_1_21_5::new; case "1.21.5" -> npcAdapter = Npc_1_21_5::new;
@@ -189,7 +191,7 @@ public class FancyNpcs extends JavaPlugin implements FancyNpcsPlugin {
fancyLogger.error("Unsupported minecraft server version."); fancyLogger.error("Unsupported minecraft server version.");
getLogger().warning("--------------------------------------------------"); getLogger().warning("--------------------------------------------------");
getLogger().warning("Unsupported minecraft server version."); getLogger().warning("Unsupported minecraft server version.");
getLogger().warning("This plugin only supports 1.19.4 - 1.21.8"); getLogger().warning("This plugin only supports 1.19.4 - 1.21.11");
getLogger().warning("Disabling the FancyNpcs plugin."); getLogger().warning("Disabling the FancyNpcs plugin.");
getLogger().warning("--------------------------------------------------"); getLogger().warning("--------------------------------------------------");
pluginManager.disablePlugin(this); pluginManager.disablePlugin(this);
@@ -275,7 +277,7 @@ public class FancyNpcs extends JavaPlugin implements FancyNpcsPlugin {
pluginManager.registerEvents(new PlayerTeleportListener(), instance); pluginManager.registerEvents(new PlayerTeleportListener(), instance);
pluginManager.registerEvents(new PlayerChangedWorldListener(), instance); pluginManager.registerEvents(new PlayerChangedWorldListener(), instance);
pluginManager.registerEvents(skinManager, instance); pluginManager.registerEvents(skinManager, instance);
if (Bukkit.getMinecraftVersion().equals("1.21.4") || Bukkit.getMinecraftVersion().equals("1.21.5") || Bukkit.getMinecraftVersion().equals("1.21.6") || Bukkit.getMinecraftVersion().equals("1.21.7") || Bukkit.getMinecraftVersion().equals("1.21.8") || Bukkit.getMinecraftVersion().equals("1.21.9") || Bukkit.getMinecraftVersion().equals("1.21.10")) { if (Set.of("1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10", "1.21.11").contains(Bukkit.getMinecraftVersion())) {
getServer().getPluginManager().registerEvents(new PlayerLoadedListener(), this); getServer().getPluginManager().registerEvents(new PlayerLoadedListener(), this);
} }

View File

@@ -33,6 +33,7 @@ import org.incendo.cloud.parser.standard.EnumParser;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.Optional; import java.util.Optional;
import static org.incendo.cloud.exception.handling.ExceptionHandler.unwrappingHandler; import static org.incendo.cloud.exception.handling.ExceptionHandler.unwrappingHandler;
@@ -184,6 +185,7 @@ public final class CloudCommandManager {
annotationParser.parse(NearbyCMD.INSTANCE); annotationParser.parse(NearbyCMD.INSTANCE);
annotationParser.parse(HelpCMD.INSTANCE); annotationParser.parse(HelpCMD.INSTANCE);
annotationParser.parse(RemoveCMD.INSTANCE); annotationParser.parse(RemoveCMD.INSTANCE);
annotationParser.parse(RotateCMD.INSTANCE);
annotationParser.parse(ShowInTabCMD.INSTANCE); annotationParser.parse(ShowInTabCMD.INSTANCE);
annotationParser.parse(SkinCMD.INSTANCE); annotationParser.parse(SkinCMD.INSTANCE);
annotationParser.parse(TeleportCMD.INSTANCE); annotationParser.parse(TeleportCMD.INSTANCE);
@@ -197,8 +199,7 @@ public final class CloudCommandManager {
annotationParser.parse(FancyNpcsDebugCMD.INSTANCE); annotationParser.parse(FancyNpcsDebugCMD.INSTANCE);
} }
String mcVersion = Bukkit.getMinecraftVersion(); if (Set.of("1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10", "1.21.11").contains(Bukkit.getMinecraftVersion())) {
if (mcVersion.equals("1.20.5") || mcVersion.equals("1.20.6") || mcVersion.equals("1.21") || mcVersion.equals("1.21.1") || mcVersion.equals("1.21.2") || mcVersion.equals("1.21.3") || mcVersion.equals("1.21.4") || mcVersion.equals("1.21.5") || mcVersion.equals("1.21.6") || mcVersion.equals("1.21.7") || Bukkit.getMinecraftVersion().equals("1.21.8") || Bukkit.getMinecraftVersion().equals("1.21.9") || Bukkit.getMinecraftVersion().equals("1.21.10")) {
annotationParser.parse(ScaleCMD.INSTANCE); annotationParser.parse(ScaleCMD.INSTANCE);
} }

View File

@@ -0,0 +1,43 @@
package de.oliver.fancynpcs.commands.npc;
import de.oliver.fancylib.translations.Translator;
import de.oliver.fancynpcs.FancyNpcs;
import de.oliver.fancynpcs.api.Npc;
import de.oliver.fancynpcs.api.events.NpcModifyEvent;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.incendo.cloud.annotations.Command;
import org.incendo.cloud.annotations.Permission;
import org.jetbrains.annotations.NotNull;
public enum RotateCMD {
INSTANCE;
private final Translator translator = FancyNpcs.getInstance().getTranslator();
@Command("npc rotate <npc> <yaw> <pitch>")
@Permission("fancynpcs.command.npc.rotate")
public void onRotate(
final @NotNull CommandSender sender,
final @NotNull Npc npc,
final float yaw,
final float pitch
) {
final Location currentLocation = npc.getData().getLocation();
final Location newLocation = currentLocation.clone();
newLocation.setYaw(yaw);
newLocation.setPitch(pitch);
if (new NpcModifyEvent(npc, NpcModifyEvent.NpcModification.ROTATION, new float[]{yaw, pitch}, sender).callEvent()) {
npc.getData().setLocation(newLocation);
npc.updateForAll();
translator.translate("npc_rotate_set_success")
.replace("npc", npc.getData().getName())
.replace("yaw", String.valueOf(yaw))
.replace("pitch", String.valueOf(pitch))
.send(sender);
} else {
translator.translate("command_npc_modification_cancelled").send(sender);
}
}
}

View File

@@ -123,6 +123,7 @@ messages:
npc_move_to: "<dark_gray> <gray>Syntax: {primaryColor}/npc move_to {secondaryColor}(npc) (x) (y) (z) [world]" npc_move_to: "<dark_gray> <gray>Syntax: {primaryColor}/npc move_to {secondaryColor}(npc) (x) (y) (z) [world]"
npc_nearby: "<dark_gray> <gray>Syntax: {primaryColor}/npc nearby {secondaryColor}[filters...]" npc_nearby: "<dark_gray> <gray>Syntax: {primaryColor}/npc nearby {secondaryColor}[filters...]"
npc_remove: "<dark_gray> <gray>Syntax: {primaryColor}/npc remove {secondaryColor}(npc)" npc_remove: "<dark_gray> <gray>Syntax: {primaryColor}/npc remove {secondaryColor}(npc)"
npc_rotate: "<dark_gray> <gray>Syntax: {primaryColor}/npc rotate {secondaryColor}(npc) (yaw) (pitch)"
npc_show_in_tab: "<dark_gray> <gray>Syntax: {primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)" npc_show_in_tab: "<dark_gray> <gray>Syntax: {primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)"
npc_skin: "<dark_gray> <gray>Syntax: {primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | uuid | placeholder | url | file name) [--slim]" npc_skin: "<dark_gray> <gray>Syntax: {primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | uuid | placeholder | url | file name) [--slim]"
npc_teleport: "<dark_gray> <gray>Syntax: {primaryColor}/npc teleport {secondaryColor}(npc)" npc_teleport: "<dark_gray> <gray>Syntax: {primaryColor}/npc teleport {secondaryColor}(npc)"
@@ -176,6 +177,7 @@ messages:
- "<dark_gray> <hover:show_text:'<gray>Teleports NPC to specified location.'>{primaryColor}/npc move_to {secondaryColor}(npc) (x) (y) (z) [world]" - "<dark_gray> <hover:show_text:'<gray>Teleports NPC to specified location.'>{primaryColor}/npc move_to {secondaryColor}(npc) (x) (y) (z) [world]"
- "<dark_gray> <hover:show_text:'<gray>Lists all NPCs in your world. Can be filtered and sorted.'>{primaryColor}/npc nearby {secondaryColor}[--radius] [--type] [--sort]" - "<dark_gray> <hover:show_text:'<gray>Lists all NPCs in your world. Can be filtered and sorted.'>{primaryColor}/npc nearby {secondaryColor}[--radius] [--type] [--sort]"
- "<dark_gray> <hover:show_text:'<gray>Removes (deletes) specified NPC.'>{primaryColor}/npc remove {secondaryColor}(npc)" - "<dark_gray> <hover:show_text:'<gray>Removes (deletes) specified NPC.'>{primaryColor}/npc remove {secondaryColor}(npc)"
- "<dark_gray> <hover:show_text:'<gray>Changes the rotation (yaw and pitch) of the NPC.'>{primaryColor}/npc rotate {secondaryColor}(npc) (yaw) (pitch)"
- "<dark_gray> <hover:show_text:'<gray>Changes the scale of the size of the NPC.'>{primaryColor}/npc scale {secondaryColor}(npc) (factor)" - "<dark_gray> <hover:show_text:'<gray>Changes the scale of the size of the NPC.'>{primaryColor}/npc scale {secondaryColor}(npc) (factor)"
- "<dark_gray> <hover:show_text:'<gray>Changes whether the NPC is shown in the player-list. This works only on NPCs of PLAYER type.<newline><newline>{errorColor}Re-connecting to the server might be required for changes to take effect.'>{primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)" - "<dark_gray> <hover:show_text:'<gray>Changes whether the NPC is shown in the player-list. This works only on NPCs of PLAYER type.<newline><newline>{errorColor}Re-connecting to the server might be required for changes to take effect.'>{primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)"
- "<dark_gray> <hover:show_text:'<gray>Changes skin of the NPC.<newline><gray>Supports PlaceholderAPI and MiniPlaceholders.<newline><newline>{warningColor}@none <dark_gray>- <gray>removes the skin<newline>{warningColor}@mirror <dark_gray>- <gray>mirrors player skin<newline>{warningColor}(name) <dark_gray>- <gray>name of any player<newline>{warningColor}(url) <dark_gray>- <gray>url of the skin texture'>{primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | url) [--slim]" - "<dark_gray> <hover:show_text:'<gray>Changes skin of the NPC.<newline><gray>Supports PlaceholderAPI and MiniPlaceholders.<newline><newline>{warningColor}@none <dark_gray>- <gray>removes the skin<newline>{warningColor}@mirror <dark_gray>- <gray>mirrors player skin<newline>{warningColor}(name) <dark_gray>- <gray>name of any player<newline>{warningColor}(url) <dark_gray>- <gray>url of the skin texture'>{primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | url) [--slim]"
@@ -302,6 +304,9 @@ messages:
# Commands (npc remove) # Commands (npc remove)
npc_remove_success: "<dark_gray> <gray>NPC {warningColor}{npc}<gray> has been removed." npc_remove_success: "<dark_gray> <gray>NPC {warningColor}{npc}<gray> has been removed."
# Commands (npc rotate)
npc_rotate_set_success: "<dark_gray> <gray>NPC {warningColor}{npc}<gray> has been rotated to yaw {warningColor}{yaw}<gray> and pitch {warningColor}{pitch}<gray>."
# Commands (scale) # Commands (scale)
npc_scale_set_success: "<dark_gray> <gray>NPC {warningColor}{npc}<gray> has been scaled to {warningColor}{scale}<gray>." npc_scale_set_success: "<dark_gray> <gray>NPC {warningColor}{npc}<gray> has been scaled to {warningColor}{scale}<gray>."

View File

@@ -2,6 +2,7 @@ rootProject.name = "minecraft-plugins"
include(":plugins:fancynpcs:") include(":plugins:fancynpcs:")
include(":plugins:fancynpcs:fn-api") include(":plugins:fancynpcs:fn-api")
include(":plugins:fancynpcs:implementation_1_21_11")
include(":plugins:fancynpcs:implementation_1_21_9") include(":plugins:fancynpcs:implementation_1_21_9")
include(":plugins:fancynpcs:implementation_1_21_6") include(":plugins:fancynpcs:implementation_1_21_6")
include(":plugins:fancynpcs:implementation_1_21_5") include(":plugins:fancynpcs:implementation_1_21_5")
@@ -46,6 +47,7 @@ include(":libraries:packets:implementations:1_21_4")
include(":libraries:packets:implementations:1_21_5") include(":libraries:packets:implementations:1_21_5")
include(":libraries:packets:implementations:1_21_6") include(":libraries:packets:implementations:1_21_6")
include(":libraries:packets:implementations:1_21_9") include(":libraries:packets:implementations:1_21_9")
include(":libraries:packets:implementations:1_21_11")
include(":tools:deployment") include(":tools:deployment")