41 Commits

Author SHA1 Message Date
Oliver
8735da08a6 Merge branch 'main' into fix/folia-visibility-issues 2025-11-18 11:33:10 +01:00
Oliver
540b3ad738 fancynpcs: Add enable-folia-visibility-fix fflag 2025-11-18 11:32:06 +01:00
Oliver
5c5f82736b Rollback ChatColorHandler 6.0.0 2025-11-09 11:34:12 +01:00
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
Oliver
455165b0f6 common: Ignore directories when loading language files 2025-11-05 12:43:53 +01:00
Oliver
f29bd13387 fancynpcs: Filter language files to only include .yml extensions 2025-11-05 12:37:22 +01:00
Oliver
7cd24f18f3 fancynpcs: Only use minecraft usercache if fflag is enabled 2025-11-05 12:28:23 +01:00
Oliver
9774f57ea6 fancydialogs: Add expectedUserInput field to ConfirmationDialog 2025-11-05 12:26:24 +01:00
Oliver
232f041df0 fancydialogs: Fix cast exception caused by close_timeout config option 2025-11-04 20:26:35 +01:00
Oliver
47e0714ec7 fancyholograms v3: Add total_amount_attached_traits metric 2025-11-04 20:22:38 +01:00
envizar
414da48403 fancynpcs: Add swing_arm_on_update option (#135) 2025-11-04 20:02:00 +01:00
Oliver
ac2a4f6e93 fancynpcs: Fix mirror skin for 1.21.9 2025-11-04 19:06:14 +01:00
Oliver
49f2dfd79a fancyholograms v3: Refactor trait commands and add warning if using dev build 2025-10-15 16:44:25 +02:00
Oliver
bef84f0366 fancydialogs: Add dialog close timeout 2025-10-15 16:26:50 +02:00
Oliver
1b2ec76eb5 fancydialogs: Remove tutorial command 2025-10-15 16:26:24 +02:00
Oliver
a85384df0c fancydialogs: Update dependencies 2025-10-15 16:26:09 +02:00
Oliver
2df8f839aa Update links in README.md 2025-10-14 23:19:46 +02:00
Oliver
a74073abd2 packets: Fix 1.21.9 tests 2025-10-14 22:17:00 +02:00
Oliver
59a063500f Update ChatColorHandler to 6.0.3 (added support for <head> tag) 2025-10-14 19:26:44 +02:00
Oliver
6042202383 fancynpcs: Update dependencies 2025-10-13 17:19:35 +02:00
Oliver
dd3d26675a fancynpcs, fancyholograms: Clear CHANGELOG.md and add current dev build number to version 2025-10-10 15:09:49 +02:00
Oliver
c53cb901ab fancyholograms: Fix version 2025-10-10 14:27:09 +02:00
Oliver
430b34a53f fancyholograms: Update version to 2.8.0 2025-10-10 14:17:15 +02:00
Oliver
bfa579db26 fancynpcs: Update version to 2.8.0 2025-10-10 14:13:49 +02:00
Oliver
e7c7b94f87 Update dependencies to 1.21.10 2025-10-10 14:12:58 +02:00
Oliver
84e15acf26 docs: Add configuration note for bungee-plugin-message-channel in action system 2025-10-07 16:18:50 +02:00
Oliver
4eed04bfef Add support for 1.21.10 2025-10-07 16:12:09 +02:00
Oliver
4cb32bd7a4 packets: Use correct protocol version for 1.21.10 2025-10-07 16:10:09 +02:00
162 changed files with 4466 additions and 488 deletions

View File

@@ -8,8 +8,8 @@
[![Hangar](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/available/hangar_vector.svg)](https://hangar.papermc.io/Oliver)
[![Unsupported spigot](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/unsupported/spigot_vector.svg)]()
[![Website](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/website_vector.svg)](https://fancyplugins.de)
[![Documentation](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/ghpages_vector.svg)](https://docs.fancyplugins.de)
[![Website](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/website_vector.svg)](https://fancyinnovations.com)
[![Documentation](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/documentation/ghpages_vector.svg)](https://docs.fancyinnovations.com)
[![discord-plural](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/compact/social/discord-plural_46h.png)](https://discord.gg/ZUgYCEJUEx)

View File

@@ -1,10 +1,8 @@
plugins {
id("com.gradleup.shadow") version "9.0.0-beta17" apply false
id("io.papermc.paperweight.userdev") version "2.0.0-beta.17" apply false
id("xyz.jpenilla.run-paper") version "2.3.1" apply false
id("de.eldoria.plugin-yml.paper") version "0.7.1" apply false
id("io.papermc.hangar-publish-plugin") version "0.1.3" apply false
id("com.modrinth.minotaur") version "2.+" apply false
id("com.gradleup.shadow") version "9.2.2" apply false
id("io.papermc.paperweight.userdev") version "2.0.0-beta.19" apply false
id("xyz.jpenilla.run-paper") version "3.0.2" apply false
id("de.eldoria.plugin-yml.paper") version "0.8.0" apply false
}
allprojects {
@@ -17,5 +15,12 @@ allprojects {
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://repo.fancyinnovations.com/releases")
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

@@ -7,6 +7,15 @@ order: 2
#
## v2.8.0 [!badge variant="info" text="2025-10-10"]
- Added support for 1.21.9 and 1.21.10
- Added support for MiniPlaceholders v3
- Improved performance by running more tasks asynchronously
- Improved logging
- Added HologramManager#isLoaded method
- Regular dev builds are now published to the BETA channel
## v2.7.0 [!badge variant="info" text="2025-07-18"]
- Added support for 1.21.7 and 1.21.8

View File

@@ -7,6 +7,17 @@ order: 2
#
## v2.8.0 [!badge variant="info" text="2025-10-10"]
- Added support for 1.21.9 and 1.21.10
- Added support for MiniPlaceholders v3
- Added permissions for each action type
- Improved logging
- Fixed various bugs for the player-npcs fflag
- Added an optional flag to disable arm swinging in Npc#update
- Added NpcManager#isLoaded method
- Regular dev builds are now published to the BETA channel
## v2.7.1 [!badge variant="info" text="2025-08-07"]
- Fixed placeholder skins not refreshing

View File

@@ -177,6 +177,13 @@ Teleports NPC to specified location.
- **Syntax**: `/npc move_to (npc) (x) (y) (z) [world] [--look-in-my-direction]`
- **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
Centers the NPC to the specified location.

View File

@@ -73,6 +73,10 @@ Syntax: `send_to_server (server name)`
Example: `/npc action (npc) (trigger) add send_to_server skyblock`
!!!info
Make sure to set `bungee-plugin-message-channel` to `true` in the velocity.toml config file. Otherwise, this action might not work properly.
!!!
### execute_random_action
Picks a random action from the remaining actions in the list and executes it. This action is useful for creating random behavior in NPCs.
@@ -118,6 +122,10 @@ Syntax: `need_permission (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
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
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
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -57,6 +57,13 @@ public class Translator {
}
for (File langFile : langFiles) {
if (!langFile.isFile()) {
continue;
}
if (!langFile.getName().endsWith(".yml")) {
continue;
}
languages.add(loadLanguageFile(langFile));
}

View File

@@ -14,7 +14,7 @@ repositories {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
compileOnly("org.jetbrains:annotations:26.0.2")

View File

@@ -18,9 +18,10 @@ allprojects {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-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:implementations:1_21_11"))
implementation(project(":libraries:packets:implementations:1_21_9"))
implementation(project(":libraries:packets:implementations:1_21_6"))
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

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.utils.AngelConverter;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
@@ -56,9 +56,9 @@ class ClientboundAddEntityPacketImplTest {
assert createdPacket.getYRot() == AngelConverter.degreesToVanillaByte(yaw);
assert createdPacket.getXRot() == AngelConverter.degreesToVanillaByte(pitch);
assert createdPacket.getYHeadRot() == AngelConverter.degreesToVanillaByte(headYaw);
assert createdPacket.getXa() == velocityX;
assert createdPacket.getYa() == velocityY;
assert createdPacket.getZa() == velocityZ;
assert createdPacket.getMovement().x == velocityX;
assert createdPacket.getMovement().y == velocityY;
assert createdPacket.getMovement().z == velocityZ;
assert createdPacket.getData() == data;
}
}

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket;
import org.junit.jupiter.api.Test;

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
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;
@@ -47,8 +47,8 @@ class ClientboundPlayerInfoUpdatePacketImplTest {
// check entry
ClientboundPlayerInfoUpdatePacket.Entry entry = createdPacket.entries().getFirst();
assert entry.profile().getId().equals(gameProfile.getUUID());
assert entry.profile().getName().equals(gameProfile.getName());
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();

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import org.junit.jupiter.api.Test;

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.utils.reflections.ReflectionUtils;
import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket;

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
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;

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import de.oliver.fancysitula.api.utils.FS_EquipmentSlot;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
import org.junit.jupiter.api.Test;

View File

@@ -1,4 +1,4 @@
package de.oliver.fancysitula.versions.v1_21_6.packets;
package de.oliver.fancysitula.versions.v1_21_9.packets;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import org.junit.jupiter.api.Test;

View File

@@ -3,7 +3,7 @@ plugins {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
}

View File

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

View File

@@ -28,6 +28,9 @@ public class PacketFactory {
List<FS_ClientboundPlayerInfoUpdatePacket.Entry> entries
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundPlayerInfoUpdatePacketImpl(actions, entries);
}
@@ -73,6 +76,9 @@ public class PacketFactory {
int velocityZ,
int data) {
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 -> {
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
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundPlayerInfoRemovePacketImpl(uuids);
}
@@ -137,6 +146,9 @@ public class PacketFactory {
List<Integer> entityIds
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundRemoveEntitiesPacketImpl(entityIds);
}
@@ -181,6 +193,9 @@ public class PacketFactory {
boolean onGround
) {
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 -> {
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
) {
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 -> {
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
) {
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 -> {
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
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetEquipmentPacketImpl(entityId, equipment);
}
@@ -317,6 +341,9 @@ public class PacketFactory {
List<Integer> passengers
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundSetPassengersPacketImpl(entityId, passengers);
}
@@ -354,6 +381,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.CreateTeam createTeam
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, createTeam);
}
@@ -390,6 +420,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.RemoveTeam removeTeam
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeTeam);
}
@@ -426,6 +459,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.UpdateTeam updateTeam
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, updateTeam);
}
@@ -462,6 +498,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.AddEntity addEntity
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, addEntity);
}
@@ -498,6 +537,9 @@ public class PacketFactory {
FS_ClientboundCreateOrUpdateTeamPacket.RemoveEntity removeEntity
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundCreateOrUpdateTeamPacketImpl(teamName, removeEntity);
}
@@ -531,6 +573,9 @@ public class PacketFactory {
FS_Dialog dialog
) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.packets.ClientboundShowDialogPacketImpl(dialog);
}
@@ -549,6 +594,9 @@ public class PacketFactory {
*/
public FS_ClientboundClearDialogPacket createClearDialogPacket() {
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 -> {
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) {
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 -> {
return new de.oliver.fancysitula.versions.v1_21_9.utils.PacketListenerImpl(packet);
}

View File

@@ -17,7 +17,7 @@ repositories {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
implementation(project(":libraries:packets"))
implementation(project(":libraries:packets:packets-api"))
@@ -39,7 +39,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.9")
minecraftVersion("1.21.10")
}
shadowJar {

View File

@@ -19,7 +19,7 @@ repositories {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
compileOnly("com.google.code.gson:gson:2.13.1")
implementation("org.jetbrains:annotations:26.0.2")

View File

@@ -1 +1 @@
0.0.24
0.0.32

View File

@@ -8,19 +8,10 @@ plugins {
id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
}
runPaper.folia.registerTask()
val supportedVersions =
listOf(
"1.21.6",
"1.21.7",
"1.21.8",
)
allprojects {
group = "de.oliver"
version = getFDVersion()
@@ -42,7 +33,7 @@ allprojects {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
implementation(project(":plugins:fancydialogs:fd-api"))
@@ -59,7 +50,7 @@ dependencies {
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.2")
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
implementation("io.github.revxrsal:lamp.common:4.0.0-rc.12")
implementation("io.github.revxrsal:lamp.bukkit:4.0.0-rc.12")
@@ -94,10 +85,10 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.9")
minecraftVersion("1.21.10")
downloadPlugins {
modrinth("fancynpcs", "2.6.0.283")
modrinth("fancynpcs", "2.8.0")
// hangar("ViaVersion", "5.3.2")
// hangar("ViaBackwards", "5.3.2")
// modrinth("multiverse-core", "4.3.11")
@@ -146,14 +137,6 @@ tasks {
}
}
tasks.publishAllPublicationsToHangar {
dependsOn("shadowJar")
}
tasks.modrinth {
dependsOn("shadowJar")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
@@ -169,34 +152,3 @@ val gitCommitMessage: Provider<String> = providers.exec {
fun getFDVersion(): String {
return file("VERSION").readText()
}
hangarPublish {
publications.register("plugin") {
version = project.version as String
id = "FancyDialogs"
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("FancyDialogs")
versionNumber.set(getFDVersion())
versionType.set("alpha")
uploadFile.set(file("build/libs/${project.name}-${getFDVersion()}.jar"))
gameVersions.addAll(supportedVersions)
loaders.add("paper")
loaders.add("folia")
changelog.set(gitCommitMessage.get())
}

View File

@@ -12,7 +12,7 @@ dependencies {
compileOnly(project(":libraries:common"))
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("org.lushplugins:ChatColorHandler:6.0.2")
implementation("org.lushplugins:ChatColorHandler:6.0.0")
implementation("org.jetbrains:annotations:24.0.0")
}

View File

@@ -4,6 +4,7 @@ import com.fancyinnovations.fancydialogs.api.data.DialogData;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -12,12 +13,12 @@ public abstract class Dialog {
protected String id;
protected DialogData data;
protected Set<UUID> viewers;
protected Map<UUID, Long> viewers; // uuid, time opened
public Dialog(String id, DialogData data) {
this.id = id;
this.data = data;
this.viewers = ConcurrentHashMap.newKeySet();
this.viewers = new ConcurrentHashMap<>();
}
public Dialog() {
@@ -49,7 +50,7 @@ public abstract class Dialog {
* @return a set of UUIDs of players who have this dialog opened
*/
public Set<UUID> getViewers() {
return Set.copyOf(viewers);
return Set.copyOf(viewers.keySet());
}
/**
@@ -58,13 +59,7 @@ public abstract class Dialog {
* @param uuid of the player to check
* @return true if the dialog is opened for the player, false otherwise
*/
public boolean isOpenedFor(UUID uuid) {
if (uuid == null) {
return false;
}
return viewers.contains(uuid);
}
public abstract boolean isOpenedFor(UUID uuid);
/***
* Checks if the dialog is opened for a specific player.
@@ -85,7 +80,8 @@ public abstract class Dialog {
if (player == null) {
return;
}
viewers.add(player.getUniqueId());
viewers.put(player.getUniqueId(), System.currentTimeMillis());
}
@ApiStatus.Internal
@@ -93,6 +89,7 @@ public abstract class Dialog {
if (player == null) {
return;
}
viewers.remove(player.getUniqueId());
}
}

View File

@@ -1,9 +1,12 @@
package com.fancyinnovations.fancydialogs.api;
package com.fancyinnovations.fancydialogs.api.dialogs;
import com.fancyinnovations.fancydialogs.api.Dialog;
import com.fancyinnovations.fancydialogs.api.FancyDialogs;
import com.fancyinnovations.fancydialogs.api.data.DialogBodyData;
import com.fancyinnovations.fancydialogs.api.data.DialogButton;
import com.fancyinnovations.fancydialogs.api.data.DialogData;
import com.fancyinnovations.fancydialogs.api.data.inputs.DialogInputs;
import com.fancyinnovations.fancydialogs.api.data.inputs.DialogTextField;
import org.bukkit.entity.Player;
import java.util.List;
@@ -19,6 +22,7 @@ public class ConfirmationDialog {
private String title = "Confirmation";
private String confirmText = "Yes";
private String cancelText = "No";
private String expectedUserInput = "";
private Dialog dialog;
private String confirmButtonId;
@@ -28,7 +32,7 @@ public class ConfirmationDialog {
private Runnable onCancel = () -> {
};
public ConfirmationDialog(String title, String question, String confirmText, String cancelText, Runnable onConfirm, Runnable onCancel) {
public ConfirmationDialog(String title, String question, String confirmText, String cancelText, String expectedUserInput, Runnable onConfirm, Runnable onCancel) {
this.title = title;
this.question = question;
this.confirmText = confirmText;
@@ -56,6 +60,11 @@ public class ConfirmationDialog {
return this;
}
public ConfirmationDialog withExpectedUserInput(String expectedUserInput) {
this.expectedUserInput = expectedUserInput;
return this;
}
public ConfirmationDialog withOnConfirm(Runnable onConfirm) {
this.onConfirm = onConfirm;
return this;
@@ -103,18 +112,31 @@ public class ConfirmationDialog {
);
this.cancelButtonId = cancelBtn.id();
List<DialogTextField> textFields = null;
if (expectedUserInput != null && !expectedUserInput.isEmpty()) {
textFields = List.of(
new DialogTextField("confirmation_user_input", "Type '" + expectedUserInput + "' to confirm", 0, "", expectedUserInput.length(), 1)
);
}
DialogInputs inputs = new DialogInputs(textFields, null, null);
DialogData dialogData = new DialogData(
"confirmation_dialog_" + UUID.randomUUID(),
title,
false,
List.of(new DialogBodyData(question)),
DialogInputs.EMPTY, // TODO add support for confirmation phrases
inputs,
List.of(confirmBtn, cancelBtn)
);
this.dialog = FancyDialogs.get().createDialog(dialogData);
}
public String getExpectedUserInput() {
return expectedUserInput;
}
public String getConfirmButtonId() {
return confirmButtonId;
}

View File

@@ -1,5 +1,6 @@
package com.fancyinnovations.fancydialogs.api;
package com.fancyinnovations.fancydialogs.api.dialogs;
import com.fancyinnovations.fancydialogs.api.FancyDialogs;
import com.fancyinnovations.fancydialogs.api.data.DialogBodyData;
import com.fancyinnovations.fancydialogs.api.data.DialogData;
import com.fancyinnovations.fancydialogs.api.data.inputs.DialogInputs;

View File

@@ -6,6 +6,8 @@ import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class DialogButtonClickedEvent extends Event {
private static final HandlerList handlerList = new HandlerList();
@@ -13,12 +15,14 @@ public class DialogButtonClickedEvent extends Event {
private final Player player;
private final String dialogId;
private final String buttonId;
private final Map<String, String> payload;
public DialogButtonClickedEvent(@NotNull Player player, @NotNull String dialogId, @NotNull String buttonId) {
public DialogButtonClickedEvent(@NotNull Player player, @NotNull String dialogId, @NotNull String buttonId, @NotNull Map<String, String> payload) {
super(!Bukkit.isPrimaryThread());
this.player = player;
this.dialogId = dialogId;
this.buttonId = buttonId;
this.payload = payload;
}
public static HandlerList getHandlerList() {
@@ -37,6 +41,10 @@ public class DialogButtonClickedEvent extends Event {
return buttonId;
}
public Map<String, String> getPayload() {
return payload;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlerList;

View File

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

View File

@@ -8,7 +8,8 @@
"1.21.6",
"1.21.7",
"1.21.8",
"1.21.9"
"1.21.9",
"1.21.10"
],
"channel": "BETA",
"loaders": [

View File

@@ -9,7 +9,6 @@ import com.fancyinnovations.fancydialogs.api.data.DialogData;
import com.fancyinnovations.fancydialogs.commands.DialogCMD;
import com.fancyinnovations.fancydialogs.commands.FancyDialogsCMD;
import com.fancyinnovations.fancydialogs.commands.QuickActionsCMD;
import com.fancyinnovations.fancydialogs.commands.TutorialCMD;
import com.fancyinnovations.fancydialogs.commands.types.DialogCommandType;
import com.fancyinnovations.fancydialogs.config.FDFeatureFlags;
import com.fancyinnovations.fancydialogs.config.FancyDialogsConfig;
@@ -243,7 +242,6 @@ public class FancyDialogsPlugin extends JavaPlugin implements FancyDialogs {
lamp.register(FancyDialogsCMD.INSTANCE);
lamp.register(DialogCMD.INSTANCE);
lamp.register(TutorialCMD.INSTANCE);
if (!FDFeatureFlags.DISABLE_QUICK_ACTIONS_DIALOG.isEnabled()) {
lamp.register(QuickActionsCMD.INSTANCE);
}

View File

@@ -1,9 +1,9 @@
package com.fancyinnovations.fancydialogs.commands;
import com.fancyinnovations.fancydialogs.FancyDialogsPlugin;
import com.fancyinnovations.fancydialogs.api.ConfirmationDialog;
import com.fancyinnovations.fancydialogs.api.Dialog;
import com.fancyinnovations.fancydialogs.api.data.DialogData;
import com.fancyinnovations.fancydialogs.api.dialogs.ConfirmationDialog;
import com.fancyinnovations.fancydialogs.config.FancyDialogsConfig;
import com.fancyinnovations.fancydialogs.dialog.DialogImpl;
import de.oliver.fancyanalytics.logger.LogLevel;

View File

@@ -1,29 +0,0 @@
package com.fancyinnovations.fancydialogs.commands;
import com.fancyinnovations.fancydialogs.FancyDialogsPlugin;
import de.oliver.fancylib.translations.Translator;
import revxrsal.commands.annotation.Command;
import revxrsal.commands.annotation.Description;
import revxrsal.commands.bukkit.actor.BukkitCommandActor;
import revxrsal.commands.bukkit.annotation.CommandPermission;
public final class TutorialCMD {
public static final TutorialCMD INSTANCE = new TutorialCMD();
private final FancyDialogsPlugin plugin = FancyDialogsPlugin.get();
private final Translator translator = FancyDialogsPlugin.get().getTranslator();
private TutorialCMD() {
}
@Command("tutorial open <tutorial>")
@Description("Opens a specific tutorial dialog")
@CommandPermission("fancydialogs.commands.tutorial")
public void onTutorialOpen(
final BukkitCommandActor actor,
final String tutorial
) {
actor.requirePlayer().sendMessage("Opening tutorial: " + tutorial);
}
}

View File

@@ -12,6 +12,7 @@ public class FancyDialogsConfig {
private String logLevel;
private String welcomeDialogID;
private String quickActionsDialogID;
private int closeTimeout;
public void load() {
FancyDialogsPlugin.get().reloadConfig();
@@ -29,6 +30,9 @@ public class FancyDialogsConfig {
quickActionsDialogID = (String) ConfigHelper.getOrDefault(config, "quick_actions_dialog_id", "quick_actions");
config.setInlineComments("quick_actions_dialog_id", List.of("The ID of the dialog which will be shown to the player when they click on the quick actions key ('G' by default)."));
closeTimeout = (int) ConfigHelper.getOrDefault(config, "close_timeout", 1000 * 60 * 2);
config.setInlineComments("close_timeout", List.of("The time in milliseconds after which a dialog will be considered closed if the player does not respond. 0 means no timeout."));
FancyDialogsPlugin.get().saveConfig();
}
@@ -47,4 +51,8 @@ public class FancyDialogsConfig {
public String getQuickActionsDialogID() {
return quickActionsDialogID;
}
public int getCloseTimeout() {
return closeTimeout;
}
}

View File

@@ -27,6 +27,7 @@ import org.lushplugins.chatcolorhandler.parsers.ParserTypes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class DialogImpl extends Dialog {
@@ -177,7 +178,7 @@ public class DialogImpl extends Dialog {
.createShowDialogPacket(buildForPlayer(player))
.send(new FS_RealPlayer(player));
viewers.add(player.getUniqueId());
addViewer(player);
FancyDialogsPlugin.get().getFancyLogger().debug("Opened dialog " + id + " for player " + player.getName());
}
@@ -188,9 +189,29 @@ public class DialogImpl extends Dialog {
.createClearDialogPacket()
.send(new FS_RealPlayer(player));
viewers.remove(player.getUniqueId());
removeViewer(player);
FancyDialogsPlugin.get().getFancyLogger().debug("Closed dialog " + id + " for player " + player.getName());
}
@Override
public boolean isOpenedFor(UUID uuid) {
if (uuid == null) {
return false;
}
if (!viewers.containsKey(uuid)) {
return false;
}
long openedAt = viewers.get(uuid);
long now = System.currentTimeMillis();
if (now - openedAt > FancyDialogsPlugin.get().getFancyDialogsConfig().getCloseTimeout()) {
viewers.remove(uuid);
return false;
}
return true;
}
}

View File

@@ -46,7 +46,7 @@ public class CustomClickActionPacketListener {
String dialogId = packet.getPayload().get("dialog_id");
String buttonId = packet.getPayload().get("button_id");
new DialogButtonClickedEvent(event.player(), dialogId, buttonId).callEvent();
new DialogButtonClickedEvent(event.player(), dialogId, buttonId, packet.getPayload()).callEvent();
if (dialogId.startsWith("confirmation_dialog_")) {
return; // Ignore confirmation dialog actions, handled separately

View File

@@ -1,6 +1,7 @@
package com.fancyinnovations.fancydialogs.listener;
import com.fancyinnovations.fancydialogs.api.ConfirmationDialog;
import com.fancyinnovations.fancydialogs.FancyDialogsPlugin;
import com.fancyinnovations.fancydialogs.api.dialogs.ConfirmationDialog;
import com.fancyinnovations.fancydialogs.api.events.DialogButtonClickedEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -16,6 +17,21 @@ public class DialogButtonClickedListener implements Listener {
}
if (event.getButtonId().equals(dialog.getConfirmButtonId())) {
if (dialog.getExpectedUserInput() != null && !dialog.getExpectedUserInput().isEmpty()) {
if (!event.getPayload().containsKey("confirmation_user_input")) {
FancyDialogsPlugin.get().getFancyLogger().warn("Confirmation dialog expected user input but none was provided.");
return;
}
String userInput = event.getPayload().get("confirmation_user_input");
if (!userInput.equals(dialog.getExpectedUserInput())) {
FancyDialogsPlugin.get().getTranslator()
.translate("confirmation_dialog.input_mismatch")
.send(event.getPlayer());
return;
}
}
dialog.getOnConfirm().run();
ConfirmationDialog.CACHE.remove(event.getDialogId());
} else if (event.getButtonId().equals(dialog.getCancelButtonId())) {

View File

@@ -2,6 +2,8 @@ language_name: default
messages:
dialog:
not_found: "<dark_gray> <gray>Dialog {warningColor}{id}<gray> is not registered."
confirmation_dialog:
input_mismatch: "<dark_gray> <gray>Your input does not match the expected phrase."
commands:
dialog:
open:

View File

@@ -1,3 +1 @@
- Improved performance by running more tasks asynchronously
- Improved logging
- Added HologramManager#isLoaded method
- Added support for 1.21.11

View File

@@ -1 +1 @@
2.7.0.154
2.8.0.158

View File

@@ -12,7 +12,7 @@ dependencies {
compileOnly(project(":libraries:common"))
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("org.lushplugins:ChatColorHandler:6.0.2")
implementation("org.lushplugins:ChatColorHandler:6.0.0")
}
tasks {

View File

@@ -8,33 +8,10 @@ plugins {
id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
}
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 {
group = "de.oliver"
version = getFHVersion()
@@ -56,7 +33,7 @@ allprojects {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms-v2:api"))
implementation(project(":plugins:fancyholograms-v2:implementation_1_20_4", configuration = "reobf"))
@@ -77,7 +54,7 @@ dependencies {
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.2")
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
compileOnly("org.geysermc.floodgate:api:2.2.4-SNAPSHOT")
}
@@ -114,7 +91,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.9")
minecraftVersion("1.21.10")
downloadPlugins {
// modrinth("fancynpcs", "2.5.2")
@@ -167,14 +144,6 @@ tasks {
}
}
tasks.publishAllPublicationsToHangar {
dependsOn("shadowJar")
}
tasks.modrinth {
dependsOn("shadowJar")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
@@ -190,34 +159,3 @@ val gitCommitMessage: Provider<String> = providers.exec {
fun getFHVersion(): String {
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

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

View File

@@ -22,7 +22,8 @@
"1.21.6",
"1.21.7",
"1.21.8",
"1.21.9"
"1.21.9",
"1.21.10"
],
"channel": "BETA",
"loaders": [

View File

@@ -292,7 +292,7 @@ public final class FancyHolograms extends JavaPlugin implements FancyHologramsPl
private void registerListeners() {
getServer().getPluginManager().registerEvents(new PlayerListener(this), 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);
}

View File

@@ -1,5 +1,6 @@
**ATTENTION**: v3 is still in development and contains breaking changes and potential bugs.
Do not use this version in production at all, or you may lose data!!
Do not use this version in production at all, or you may lose data!
Once migrated to v3, you cannot go back to v2 without losing all your holograms and configurations!
Commit hash: %COMMIT_HASH%

View File

@@ -1 +1 @@
3.0.0-SNAPSHOT.6
3.0.0-SNAPSHOT.11

View File

@@ -8,27 +8,10 @@ plugins {
id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
}
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 {
group = "de.oliver"
version = getFHVersion()
@@ -50,7 +33,7 @@ allprojects {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-R0.1-SNAPSHOT")
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms:fh-api"))
@@ -70,7 +53,7 @@ dependencies {
implementation("io.github.revxrsal:lamp.common:4.0.0-rc.12")
implementation("io.github.revxrsal:lamp.bukkit:4.0.0-rc.12")
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.2")
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
compileOnly("com.viaversion:viaversion-api:5.2.1")
compileOnly("org.geysermc.floodgate:api:2.2.4-SNAPSHOT")
}
@@ -113,7 +96,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.9")
minecraftVersion("1.21.10")
downloadPlugins {
modrinth("fancynpcs", "2.7.0")
@@ -162,14 +145,6 @@ tasks {
}
}
tasks.publishAllPublicationsToHangar {
dependsOn("shadowJar")
}
tasks.modrinth {
dependsOn("shadowJar")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
@@ -185,34 +160,3 @@ fun getLastCommitMessage(): String {
fun getFHVersion(): String {
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

@@ -13,7 +13,7 @@ dependencies {
compileOnly(project(":libraries:jdb"))
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("org.lushplugins:ChatColorHandler:6.0.2")
implementation("org.lushplugins:ChatColorHandler:6.0.0")
}
tasks {

View File

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

View File

@@ -16,7 +16,8 @@
"1.21.6",
"1.21.7",
"1.21.8",
"1.21.9"
"1.21.9",
"1.21.10"
],
"channel": "ALPHA",
"loaders": [

View File

@@ -202,10 +202,6 @@ public final class HologramCMD extends Command {
return Collections.emptyList();
}
if (args[2].equalsIgnoreCase("traits")) {
return new TraitsCMD().tabcompletion(sender, hologram, args);
}
// /holo edit [hologram] [option] {tab:contextual}
if (args.length == 4) {
final var suggestions = switch (args[2].toLowerCase(Locale.ROOT)) {
@@ -354,9 +350,6 @@ public final class HologramCMD extends Command {
}
return switch (action) {
// hologram data
case "traits" -> new TraitsCMD().run(player, hologram, args);
// display data
case "moveto" -> new MoveToCMD().run(player, hologram, args);
case "rotate" -> new RotateCMD().run(player, hologram, args);

View File

@@ -1,94 +0,0 @@
package com.fancyinnovations.fancyholograms.commands.hologram;
import com.fancyinnovations.fancyholograms.api.FancyHolograms;
import com.fancyinnovations.fancyholograms.api.hologram.Hologram;
import com.fancyinnovations.fancyholograms.api.trait.HologramTraitRegistry;
import com.fancyinnovations.fancyholograms.commands.Subcommand;
import de.oliver.fancylib.MessageHelper;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class TraitsCMD implements Subcommand {
@Override
public List<String> tabcompletion(@NotNull CommandSender player, @Nullable Hologram hologram, @NotNull String[] args) {
if (args.length == 4) {
return List.of("add", "remove");
} else if (args.length == 5) {
return FancyHolograms.get().getTraitRegistry().getTraits()
.stream()
.filter(ti -> !ti.isDefault())
.filter(ti -> {
if (args[3].equalsIgnoreCase("add")) {
return !hologram.getData().getTraitTrait().isTraitAttached(ti.clazz());
} else if (args[3].equalsIgnoreCase("remove")) {
return hologram.getData().getTraitTrait().isTraitAttached(ti.clazz());
}
return true;
})
.map(HologramTraitRegistry.TraitInfo::name)
.toList();
}
return List.of();
}
@Override
public boolean run(@NotNull CommandSender player, @Nullable Hologram hologram, @NotNull String[] args) {
if (!(player.hasPermission("fancyholograms.hologram.edit.traits"))) {
MessageHelper.error(player, "You don't have the required permission to change traits of a hologram.");
return false;
}
// /hologram edit <name> traits <add|remove> <trait name>
if (args.length < 5) {
MessageHelper.error(player, "Usage: /hologram edit <name> traits <add|remove> <trait name>");
return false;
}
String action = args[3];
String traitName = args[4];
if (traitName == null || traitName.isEmpty()) {
MessageHelper.error(player, "You must specify a trait name.");
return false;
}
HologramTraitRegistry.TraitInfo traitInfo = FancyHolograms.get().getTraitRegistry().getTrait(traitName);
if (traitInfo == null) {
MessageHelper.error(player, "Trait '" + traitName + "' does not exist.");
return false;
}
switch (action.toLowerCase()) {
case "add": {
if (hologram.getData().getTraitTrait().isTraitAttached(traitInfo.clazz())) {
MessageHelper.error(player, "Trait '" + traitName + "' is already attached to hologram '" + hologram.getData().getName() + "'.");
return false;
}
hologram.getData().getTraitTrait().addTrait(traitInfo.clazz());
MessageHelper.success(player, "Trait '" + traitName + "' has been added to hologram '" + hologram.getData().getName() + "'.");
return true;
}
case "remove": {
if (!hologram.getData().getTraitTrait().isTraitAttached(traitInfo.clazz())) {
MessageHelper.error(player, "Trait '" + traitName + "' is not attached to hologram '" + hologram.getData().getName() + "'.");
return false;
}
hologram.getData().getTraitTrait().removeTrait(traitInfo.clazz());
MessageHelper.success(player, "Trait '" + traitName + "' has been removed from hologram '" + hologram.getData().getName() + "'.");
return true;
}
default: {
MessageHelper.error(player, "Invalid action. Use 'add' or 'remove'.");
return false;
}
}
}
}

View File

@@ -1,7 +1,9 @@
package com.fancyinnovations.fancyholograms.commands.lampCommands.hologram;
import com.fancyinnovations.fancyholograms.api.hologram.Hologram;
import com.fancyinnovations.fancyholograms.api.trait.HologramTrait;
import com.fancyinnovations.fancyholograms.api.trait.HologramTraitRegistry;
import com.fancyinnovations.fancyholograms.api.trait.HologramTraitTrait;
import com.fancyinnovations.fancyholograms.commands.lampCommands.suggestions.AttachedTraitsSuggestion;
import com.fancyinnovations.fancyholograms.commands.lampCommands.suggestions.DetachedTraitsSuggestion;
import com.fancyinnovations.fancyholograms.main.FancyHologramsPlugin;
@@ -70,4 +72,30 @@ public final class TraitCMD {
.replace("name", trait.name())
.send(actor.sender());
}
@Command("hologram-new edit <hologram> trait list")
@Description("Lists all attached traits of a hologram")
@CommandPermission("fancyholograms.commands.hologram.trait.list")
public void list(
final @NotNull BukkitCommandActor actor,
final @NotNull Hologram hologram
) {
HologramTraitTrait traitTrait = hologram.getData().getTraitTrait();
if (traitTrait.getTraits().isEmpty()) {
translator.translate("commands.hologram.edit.trait.list.no_traits")
.replace("hologram", hologram.getData().getName())
.send(actor.sender());
return;
}
translator.translate("commands.hologram.edit.trait.list.header")
.replace("hologram", hologram.getData().getName())
.send(actor.sender());
for (HologramTrait trait : traitTrait.getTraits()) {
translator.translate("commands.hologram.edit.trait.list.entry")
.replace("name", trait.getName())
.send(actor.sender());
}
}
}

View File

@@ -212,6 +212,17 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog
if (!configuration.areVersionNotificationsMuted()) {
checkForNewerVersion();
}
if (versionConfig.isDevelopmentBuild()) {
fancyLogger.warn("""
--------------------------------------------------
You are using a development build of FancyHolograms.
Please be aware that there might be bugs in this version.
If you find any bugs, please report them on our discord server (https://discord.gg/ZUgYCEJUEx).
Read more about the risks of using a development build here: https://docs.fancyinnovations.com/development-guidelines/versioning/#build
--------------------------------------------------
""");
}
metrics.register();
metrics.registerLegacy();
@@ -300,7 +311,7 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog
getServer().getPluginManager().registerEvents(new PlayerListener(this), 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);
}

View File

@@ -1,6 +1,7 @@
package com.fancyinnovations.fancyholograms.metrics;
import com.fancyinnovations.fancyholograms.api.HologramRegistry;
import com.fancyinnovations.fancyholograms.api.hologram.Hologram;
import com.fancyinnovations.fancyholograms.main.FancyHologramsPlugin;
import de.oliver.fancyanalytics.api.FancyAnalyticsAPI;
import de.oliver.fancyanalytics.api.metrics.MetricSupplier;
@@ -74,6 +75,14 @@ public class FHMetrics {
.toArray(String[]::new);
}));
fancyAnalytics.registerNumberMetric(new MetricSupplier<>("total_amount_attached_traits", () -> {
double total = 0d;
for (Hologram hologram : registry.getAll()) {
total += hologram.getData().getTraitTrait().getTraits().size();
}
return total;
}));
fancyAnalytics.initialize();
}

View File

@@ -21,3 +21,7 @@ messages:
detach:
not_attached: "<dark_gray> <gray>Hologram {warningColor}{hologram}<gray> does not have trait {warningColor}{name}<gray> attached."
success: "<dark_gray> <gray>Successfully detached trait {warningColor}{name}<gray> from hologram {warningColor}{hologram}<gray>."
list:
no_traits: "<dark_gray> <gray>Hologram {warningColor}{hologram}<gray> does not have any traits attached."
header: "<dark_gray> <gray>Hologram {warningColor}{hologram}<gray> has the following traits attached:"
entry: "<dark_gray> <gray> - {warningColor}{name}<gray>"

View File

@@ -1,6 +1,6 @@
- Added support for MiniPlaceholders v3
- Added permissions for each action type
- Improved logging
- Fixed various bugs for the player-npcs fflag
- Added an optional flag to disable arm swinging in Npc#update
- Added NpcManager#isLoaded method
- 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
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.

View File

@@ -1 +1 @@
2.7.1.299
2.8.0.308

View File

@@ -6,35 +6,10 @@ plugins {
id("xyz.jpenilla.run-paper")
id("com.gradleup.shadow")
id("de.eldoria.plugin-yml.paper")
id("io.papermc.hangar-publish-plugin")
id("com.modrinth.minotaur")
}
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 {
group = "de.oliver"
version = getFNVersion()
@@ -53,9 +28,10 @@ allprojects {
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.9-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:implementation_1_21_11"))
implementation(project(":plugins:fancynpcs:implementation_1_21_9"))
implementation(project(":plugins:fancynpcs:implementation_1_21_6"))
implementation(project(":plugins:fancynpcs:implementation_1_21_5"))
@@ -78,12 +54,12 @@ dependencies {
implementation(project(":libraries:jdb"))
implementation(project(":libraries:plugin-tests"))
implementation(project(":libraries:config"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.2")
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
implementation("de.oliver.FancyAnalytics:java-sdk:0.0.4")
implementation("de.oliver.FancyAnalytics:mc-api:0.1.11")
implementation("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("org.incendo:cloud-core:2.0.0")
implementation("org.incendo:cloud-paper:2.0.0-beta.11")
implementation("org.incendo:cloud-paper:2.0.0-beta.13")
implementation("org.incendo:cloud-annotations:2.0.0")
annotationProcessor("org.incendo:cloud-annotations:2.0.0")
implementation("org.mineskin:java-client-jsoup:3.0.3-SNAPSHOT")
@@ -120,7 +96,7 @@ paper {
tasks {
runServer {
minecraftVersion("1.21.9")
minecraftVersion("1.21.10")
downloadPlugins {
// hangar("ViaVersion", "5.4.0")
@@ -204,14 +180,6 @@ tasks {
}
}
tasks.publishAllPublicationsToHangar {
dependsOn(":plugins:fancynpcs:shadowJar")
}
tasks.modrinth {
dependsOn(":plugins:fancynpcs:shadowJar")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}
@@ -227,34 +195,3 @@ val gitCommitMessage: Provider<String> = providers.exec {
fun getFNVersion(): String {
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

@@ -10,9 +10,10 @@ dependencies {
compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")
compileOnly(project(":libraries:common"))
compileOnly(project(":libraries:config"))
compileOnly("de.oliver.FancyAnalytics:logger:0.0.8")
implementation("org.lushplugins:ChatColorHandler:6.0.2")
implementation("org.lushplugins:ChatColorHandler:6.0.0")
}
tasks {

View File

@@ -35,6 +35,8 @@ public interface FancyNpcsConfig {
int getRemoveNpcsFromPlayerlistDelay();
boolean isSwingArmOnUpdate();
String getMineSkinApiKey();
List<String> getBlockedCommands();

View File

@@ -1,5 +1,6 @@
package de.oliver.fancynpcs.api;
import com.fancyinnovations.config.featureflags.FeatureFlagConfig;
import de.oliver.fancyanalytics.logger.ExtendedFancyLogger;
import de.oliver.fancylib.serverSoftware.schedulers.FancyScheduler;
import de.oliver.fancylib.translations.Translator;
@@ -32,8 +33,8 @@ public interface FancyNpcsPlugin {
ScheduledExecutorService getNpcThread();
/**
* Creates a new thread with the given name and runnable.
* Warning: Do not use this method, it is for internal use only.
* Creates a new thread with the given name and runnable.
* Warning: Do not use this method, it is for internal use only.
*/
@ApiStatus.Internal
Thread newThread(String name, Runnable runnable);
@@ -44,6 +45,8 @@ public interface FancyNpcsPlugin {
FancyNpcsConfig getFancyNpcConfig();
FeatureFlagConfig getFeatureFlagConfig();
NpcManager getNpcManager();
AttributeManager getAttributeManager();

View File

@@ -114,7 +114,7 @@ public abstract class Npc {
spawn(player);
// Respawn the npc to fix visibility issues on Folia
if (ServerSoftware.isFolia()) {
if (ServerSoftware.isFolia() && FancyNpcsPlugin.get().getFeatureFlagConfig().getFeatureFlag("enable-folia-visibility-fix").isEnabled()) {
FancyNpcsPlugin.get().getNpcThread().schedule(() -> {
remove(player);
spawn(player);
@@ -132,7 +132,7 @@ public abstract class Npc {
public abstract void update(Player player, boolean swingArm);
public void update(Player player) {
update(player, true);
update(player, FancyNpcsPlugin.get().getFancyNpcConfig().isSwingArmOnUpdate());
}
public void updateForAll(boolean swingArm) {
@@ -142,13 +142,13 @@ public abstract class Npc {
}
public void updateForAll() {
updateForAll(true);
updateForAll(FancyNpcsPlugin.get().getFancyNpcConfig().isSwingArmOnUpdate());
}
public abstract void move(Player player, boolean swingArm);
public void move(Player player) {
move(player, true);
move(player, FancyNpcsPlugin.get().getFancyNpcConfig().isSwingArmOnUpdate());
}
public void moveForAll(boolean swingArm) {
@@ -158,7 +158,7 @@ public abstract class Npc {
}
public void moveForAll() {
moveForAll(true);
moveForAll(FancyNpcsPlugin.get().getFancyNpcConfig().isSwingArmOnUpdate());
}
public void interact(Player player) {

View File

@@ -20,7 +20,13 @@ public class NeedPermissionAction extends NpcAction {
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());
context.terminate();
}

View File

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

View File

@@ -10,7 +10,7 @@ dependencies {
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly(project(":libraries:common"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.2")
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
}

View File

@@ -10,7 +10,7 @@ dependencies {
compileOnly(project(":plugins:fancynpcs:fn-api"))
compileOnly(project(":libraries:common"))
compileOnly("org.lushplugins:ChatColorHandler:6.0.2")
compileOnly("org.lushplugins:ChatColorHandler:6.0.0")
}

Some files were not shown because too many files have changed in this diff Show More