From d7d0a540387271222b38880a4a85c2fb32c2ecf3 Mon Sep 17 00:00:00 2001 From: david Date: Fri, 17 Jan 2025 21:56:16 +0100 Subject: [PATCH] Reorganized code. Reorganized methods and attributes for better structure and clarity across multiple classes. --- .../net/thenextlvl/character/Character.java | 40 ++-- .../thenextlvl/character/PlayerCharacter.java | 10 +- .../character/action/ClickAction.java | 61 +++-- .../character/plugin/CharacterPlugin.java | 125 +++++----- .../plugin/character/PaperCharacter.java | 195 ++++++++-------- .../character/PaperPlayerCharacter.java | 220 +++++++++--------- .../character/PaperSkinPartBuilder.java | 20 +- .../CharacterActionPermissionCommand.java | 18 +- .../plugin/command/CharacterSkinCommand.java | 91 ++++---- .../plugin/command/CharacterTagCommand.java | 56 ++--- .../command/CharacterTeleportCommand.java | 40 ++-- ...CharacterWithActionSuggestionProvider.java | 12 +- .../plugin/listener/ConnectionListener.java | 10 +- .../plugin/network/EmptyChannel.java | 42 ++-- .../plugin/network/EmptyConnection.java | 22 +- .../serialization/CharacterSerializer.java | 9 +- 16 files changed, 491 insertions(+), 480 deletions(-) diff --git a/api/src/main/java/net/thenextlvl/character/Character.java b/api/src/main/java/net/thenextlvl/character/Character.java index 3403fc5..770725b 100644 --- a/api/src/main/java/net/thenextlvl/character/Character.java +++ b/api/src/main/java/net/thenextlvl/character/Character.java @@ -27,6 +27,8 @@ public interface Character { @Nullable Component getDisplayName(); + void setDisplayName(@Nullable Component displayName); + EntityType getType(); @Nullable @@ -35,16 +37,22 @@ public interface Character { @Nullable Location getSpawnLocation(); + void setSpawnLocation(@Nullable Location location); + @Unmodifiable Map> getActions(); @Nullable NamedTextColor getGlowColor(); + void setGlowColor(@Nullable NamedTextColor color); + Optional getEntity(); Pose getPose(); + void setPose(Pose pose); + @Unmodifiable Set getViewers(); @@ -71,22 +79,34 @@ public interface Character { boolean isCollidable(); + void setCollidable(boolean collidable); + boolean isDisplayNameVisible(); + void setDisplayNameVisible(boolean visible); + boolean isInvincible(); + void setInvincible(boolean invincible); + boolean isPersistent(); + void setPersistent(boolean persistent); + boolean isSpawned(); boolean isTicking(); + void setTicking(boolean ticking); + boolean isTrackedBy(Player player); boolean isViewer(UUID player); boolean isVisibleByDefault(); + void setVisibleByDefault(boolean visible); + boolean persist(); boolean removeAction(String name); @@ -105,25 +125,5 @@ public interface Character { void remove(); - void setCollidable(boolean collidable); - - void setDisplayName(@Nullable Component displayName); - - void setDisplayNameVisible(boolean visible); - - void setGlowColor(@Nullable NamedTextColor color); - void setGravity(boolean gravity); - - void setInvincible(boolean invincible); - - void setPersistent(boolean persistent); - - void setPose(Pose pose); - - void setSpawnLocation(@Nullable Location location); - - void setTicking(boolean ticking); - - void setVisibleByDefault(boolean visible); } diff --git a/api/src/main/java/net/thenextlvl/character/PlayerCharacter.java b/api/src/main/java/net/thenextlvl/character/PlayerCharacter.java index 2cf2288..e78fffa 100644 --- a/api/src/main/java/net/thenextlvl/character/PlayerCharacter.java +++ b/api/src/main/java/net/thenextlvl/character/PlayerCharacter.java @@ -18,19 +18,19 @@ public interface PlayerCharacter extends Character { SkinParts getSkinParts(); + void setSkinParts(SkinParts builder); + UUID getUniqueId(); boolean clearTextures(); boolean isListed(); - boolean isRealPlayer(); - - boolean setTextures(String value, @Nullable String signature); - void setListed(boolean listed); + boolean isRealPlayer(); + void setRealPlayer(boolean real); - void setSkinParts(SkinParts builder); + boolean setTextures(String value, @Nullable String signature); } diff --git a/api/src/main/java/net/thenextlvl/character/action/ClickAction.java b/api/src/main/java/net/thenextlvl/character/action/ClickAction.java index 2b34ddf..7b44e6c 100644 --- a/api/src/main/java/net/thenextlvl/character/action/ClickAction.java +++ b/api/src/main/java/net/thenextlvl/character/action/ClickAction.java @@ -12,11 +12,12 @@ @NullMarked public class ClickAction { + private final ActionType actionType; + private final Map cooldowns = new WeakHashMap<>(); private @Nullable String permission; private EnumSet clickTypes; private Duration cooldown; private T input; - private final ActionType actionType; public ClickAction(ActionType actionType, EnumSet clickTypes, T input) { this(actionType, clickTypes, input, Duration.ZERO, null); @@ -30,23 +31,10 @@ public ClickAction(ActionType actionType, EnumSet clickTypes, T in this.permission = permission; } - private final Map cooldowns = new WeakHashMap<>(); - - public boolean isOnCooldown(Player player) { - return cooldown.isPositive() && cooldowns.computeIfPresent(player, (ignored, lastUsed) -> { - if (System.currentTimeMillis() - cooldown.toMillis() > lastUsed) return null; - return lastUsed; - }) != null; - } - public boolean resetCooldown(Player player) { return cooldowns.remove(player) != null; } - public boolean canInvoke(Player player) { - return (permission == null || player.hasPermission(permission)) && !isOnCooldown(player); - } - public boolean invoke(Player player) { if (!canInvoke(player)) return false; if (cooldown.isPositive()) cooldowns.put(player, System.currentTimeMillis()); @@ -54,30 +42,29 @@ public boolean invoke(Player player) { return true; } - public boolean isSupportedClickType(ClickType type) { - return clickTypes.contains(type); + public boolean canInvoke(Player player) { + return (permission == null || player.hasPermission(permission)) && !isOnCooldown(player); } - public void setClickTypes(EnumSet clickTypes) { - this.clickTypes = clickTypes; + public boolean isOnCooldown(Player player) { + return cooldown.isPositive() && cooldowns.computeIfPresent(player, (ignored, lastUsed) -> { + if (System.currentTimeMillis() - cooldown.toMillis() > lastUsed) return null; + return lastUsed; + }) != null; } - public void setCooldown(Duration cooldown) { - this.cooldown = cooldown; + public boolean isSupportedClickType(ClickType type) { + return clickTypes.contains(type); } - public void setInput(T input) { - this.input = input; + public @Nullable String getPermission() { + return permission; } public void setPermission(@Nullable String permission) { this.permission = permission; } - public @Nullable String getPermission() { - return permission; - } - public ActionType getActionType() { return actionType; } @@ -86,14 +73,31 @@ public Duration getCooldown() { return cooldown; } + public void setCooldown(Duration cooldown) { + this.cooldown = cooldown; + } + public EnumSet getClickTypes() { return clickTypes; } + public void setClickTypes(EnumSet clickTypes) { + this.clickTypes = clickTypes; + } + public T getInput() { return input; } + public void setInput(T input) { + this.input = input; + } + + @Override + public int hashCode() { + return Objects.hash(permission, clickTypes, cooldown, input, actionType, cooldowns); + } + @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; @@ -104,9 +108,4 @@ public boolean equals(Object o) { && Objects.equals(input, that.input) && Objects.equals(actionType, that.actionType); } - - @Override - public int hashCode() { - return Objects.hash(permission, clickTypes, cooldown, input, actionType, cooldowns); - } } diff --git a/src/main/java/net/thenextlvl/character/plugin/CharacterPlugin.java b/src/main/java/net/thenextlvl/character/plugin/CharacterPlugin.java index 2626b62..8d192b9 100644 --- a/src/main/java/net/thenextlvl/character/plugin/CharacterPlugin.java +++ b/src/main/java/net/thenextlvl/character/plugin/CharacterPlugin.java @@ -32,7 +32,19 @@ import net.thenextlvl.character.plugin.listener.ConnectionListener; import net.thenextlvl.character.plugin.listener.EntityListener; import net.thenextlvl.character.plugin.listener.test; -import net.thenextlvl.character.plugin.serialization.*; +import net.thenextlvl.character.plugin.serialization.ActionTypeAdapter; +import net.thenextlvl.character.plugin.serialization.AddressAdapter; +import net.thenextlvl.character.plugin.serialization.CharacterSerializer; +import net.thenextlvl.character.plugin.serialization.ClickActionAdapter; +import net.thenextlvl.character.plugin.serialization.ComponentAdapter; +import net.thenextlvl.character.plugin.serialization.EntityTypeAdapter; +import net.thenextlvl.character.plugin.serialization.KeyAdapter; +import net.thenextlvl.character.plugin.serialization.LocationAdapter; +import net.thenextlvl.character.plugin.serialization.ProfilePropertyAdapter; +import net.thenextlvl.character.plugin.serialization.SoundAdapter; +import net.thenextlvl.character.plugin.serialization.TitleAdapter; +import net.thenextlvl.character.plugin.serialization.TitleTimesAdapter; +import net.thenextlvl.character.plugin.serialization.WorldAdapter; import org.bstats.bukkit.Metrics; import org.bukkit.Location; import org.bukkit.World; @@ -82,10 +94,23 @@ public class CharacterPlugin extends JavaPlugin { .registerTypeHierarchyAdapter(Title.class, new TitleAdapter()) .registerTypeHierarchyAdapter(World.class, new WorldAdapter(getServer())) .build(); + private final PaperCharacterController characterController = new PaperCharacterController(this); private final PaperCharacterProvider characterProvider = new PaperCharacterProvider(this); private final PluginMessenger messenger = new PluginMessenger(this); + public final ActionType sendActionbar = register(new PaperActionType<>("send_actionbar", Component.class, Audience::sendActionBar)); + public final ActionType sendMessage = register(new PaperActionType<>("send_message", Component.class, Audience::sendMessage)); + public final ActionType transfer = register(new PaperActionType<>("transfer", InetSocketAddress.class, + (player, address) -> player.transfer(address.getHostName(), address.getPort()))); + public final ActionType teleport = (register(new PaperActionType<>("teleport", Location.class, Entity::teleportAsync))); + public final ActionType playSound = register(new PaperActionType<>("play_sound", Sound.class, Audience::playSound)); + public final ActionType runConsoleCommand = register(new PaperActionType<>("run_console_command", String.class, + (player, command) -> player.getServer().dispatchCommand(player.getServer().getConsoleSender(), command))); + public final ActionType runCommand = register(new PaperActionType<>("run_command", String.class, Player::performCommand)); + public final ActionType sendTitle = register(new PaperActionType<>("send_title", Title.class, Audience::showTitle)); + public final ActionType<String> connect = register(new PaperActionType<>("connect", String.class, messenger::connect)); + private final ComponentBundle bundle = new ComponentBundle(translations, audience -> audience instanceof Player player ? player.locale() : Locale.US) .register("messages", Locale.US) @@ -101,6 +126,15 @@ public void onLoad() { getServer().getServicesManager().register(CharacterProvider.class, characterProvider, this, ServicePriority.Highest); } + @Override + public void onDisable() { + characterController.getCharacters().forEach(character -> { + character.persist(); + character.despawn(); + }); + metrics.shutdown(); + } + @Override public void onEnable() { readAll().forEach(character -> { @@ -112,26 +146,26 @@ public void onEnable() { registerListeners(); } - @Override - public void onDisable() { - characterController.getCharacters().forEach(character -> { - character.persist(); - character.despawn(); - }); - metrics.shutdown(); - } - - private void registerCommands() { - getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS.newHandler(event -> - event.registrar().register(CharacterCommand.create(this), List.of("npc")))); + public @Unmodifiable List<Character<?>> readAll() { + var files = savesFolder.listFiles((file, name) -> name.endsWith(".dat")); + return files == null ? List.of() : Arrays.stream(files) + .map(this::readSafe) + .filter(Objects::nonNull) + .collect(Collectors.toUnmodifiableList()); } - private void registerListeners() { - getServer().getPluginManager().registerEvents(new CharacterListener(), this); - getServer().getPluginManager().registerEvents(new ConnectionListener(this), this); - getServer().getPluginManager().registerEvents(new EntityListener(this), this); - - getServer().getPluginManager().registerEvents(new test(this), this); + public Character<?> read(File file) throws IOException { + try (var inputStream = stream(IO.of(file))) { + return read(inputStream); + } catch (Exception e) { + var io = IO.of(file.getPath() + "_old"); + if (!io.exists()) throw e; + getComponentLogger().warn("Failed to load character from {}", file.getPath(), e); + getComponentLogger().warn("Falling back to {}", io); + try (var inputStream = stream(io)) { + return read(inputStream); + } + } } public ComponentBundle bundle() { @@ -154,12 +188,17 @@ public PaperCharacterProvider characterProvider() { return characterProvider; } - public @Unmodifiable List<Character<?>> readAll() { - var files = savesFolder.listFiles((file, name) -> name.endsWith(".dat")); - return files == null ? List.of() : Arrays.stream(files) - .map(this::readSafe) - .filter(Objects::nonNull) - .collect(Collectors.toUnmodifiableList()); + private void registerCommands() { + getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS.newHandler(event -> + event.registrar().register(CharacterCommand.create(this), List.of("npc")))); + } + + private void registerListeners() { + getServer().getPluginManager().registerEvents(new CharacterListener(), this); + getServer().getPluginManager().registerEvents(new ConnectionListener(this), this); + getServer().getPluginManager().registerEvents(new EntityListener(this), this); + + getServer().getPluginManager().registerEvents(new test(this), this); } private @Nullable Character<?> readSafe(File file) { @@ -175,20 +214,6 @@ public PaperCharacterProvider characterProvider() { } } - public Character<?> read(File file) throws IOException { - try (var inputStream = stream(IO.of(file))) { - return read(inputStream); - } catch (Exception e) { - var io = IO.of(file.getPath() + "_old"); - if (!io.exists()) throw e; - getComponentLogger().warn("Failed to load character from {}", file.getPath(), e); - getComponentLogger().warn("Falling back to {}", io); - try (var inputStream = stream(io)) { - return read(inputStream); - } - } - } - private NBTInputStream stream(IO file) throws IOException { return new NBTInputStream(file.inputStream(READ), StandardCharsets.UTF_8); } @@ -206,11 +231,6 @@ private Character<?> read(NBTInputStream inputStream) throws IOException { return character; } - private Character<?> createCharacter(CompoundTag root, String name, EntityType type) { - var character = characterController.createCharacter(name, type); - return deserialize(root, character); - } - private PlayerCharacter createPlayerCharacter(CompoundTag root, String name) { var uuid = root.optional("uuid").map(tag -> nbt.fromTag(tag, UUID.class)).orElseGet(UUID::randomUUID); var character = characterController.createCharacter(name, uuid); @@ -225,6 +245,11 @@ private PlayerCharacter createPlayerCharacter(CompoundTag root, String name) { return deserialize(root, character); } + private Character<?> createCharacter(CompoundTag root, String name, EntityType type) { + var character = characterController.createCharacter(name, type); + return deserialize(root, character); + } + private <T extends Character<?>> T deserialize(CompoundTag root, T character) { root.optional("collidable").map(Tag::getAsBoolean).ifPresent(character::setCollidable); root.optional("displayName").map(tag -> nbt.fromTag(tag, Component.class)) @@ -240,18 +265,6 @@ private <T extends Character<?>> T deserialize(CompoundTag root, T character) { return character; } - public final ActionType<Component> sendActionbar = register(new PaperActionType<>("send_actionbar", Component.class, Audience::sendActionBar)); - public final ActionType<Component> sendMessage = register(new PaperActionType<>("send_message", Component.class, Audience::sendMessage)); - public final ActionType<InetSocketAddress> transfer = register(new PaperActionType<>("transfer", InetSocketAddress.class, - (player, address) -> player.transfer(address.getHostName(), address.getPort()))); - public final ActionType<Location> teleport = (register(new PaperActionType<>("teleport", Location.class, Entity::teleportAsync))); - public final ActionType<Sound> playSound = register(new PaperActionType<>("play_sound", Sound.class, Audience::playSound)); - public final ActionType<String> connect = register(new PaperActionType<>("connect", String.class, messenger::connect)); - public final ActionType<String> runConsoleCommand = register(new PaperActionType<>("run_console_command", String.class, (player, command) -> - player.getServer().dispatchCommand(player.getServer().getConsoleSender(), command))); - public final ActionType<String> runCommand = register(new PaperActionType<>("run_command", String.class, Player::performCommand)); - public final ActionType<Title> sendTitle = register(new PaperActionType<>("send_title", Title.class, Audience::showTitle)); - private <T> ActionType<T> register(ActionType<T> actionType) { return characterProvider().getActionRegistry().register(actionType); } diff --git a/src/main/java/net/thenextlvl/character/plugin/character/PaperCharacter.java b/src/main/java/net/thenextlvl/character/plugin/character/PaperCharacter.java index df4dbac..64db2aa 100644 --- a/src/main/java/net/thenextlvl/character/plugin/character/PaperCharacter.java +++ b/src/main/java/net/thenextlvl/character/plugin/character/PaperCharacter.java @@ -41,6 +41,12 @@ @NullMarked public class PaperCharacter<T extends Entity> implements Character<T> { + protected final EntityType type; + protected final Map<String, ClickAction<?>> actions = new HashMap<>(); + protected final Set<UUID> viewers = new HashSet<>(); + protected final String name; + protected final CharacterPlugin plugin; + protected @Nullable Component displayName = null; protected @Nullable Location spawnLocation = null; protected @Nullable NamedTextColor glowColor = null; @@ -56,13 +62,6 @@ public class PaperCharacter<T extends Entity> implements Character<T> { protected boolean ticking = false; protected boolean visibleByDefault = true; - protected final EntityType type; - protected final Map<String, ClickAction<?>> actions = new HashMap<>(); - protected final Set<UUID> viewers = new HashSet<>(); - protected final String name; - - protected final CharacterPlugin plugin; - public PaperCharacter(CharacterPlugin plugin, String name, EntityType type) { this.name = name; this.plugin = plugin; @@ -79,6 +78,13 @@ public ClickAction<?> getAction(String name) { return displayName; } + @Override + public void setDisplayName(@Nullable Component displayName) { + if (displayName == this.displayName) return; + this.displayName = displayName; + getEntity().ifPresent(this::updateDisplayName); + } + @Override public EntityType getType() { return type; @@ -94,6 +100,11 @@ public EntityType getType() { return spawnLocation; } + @Override + public void setSpawnLocation(@Nullable Location location) { + this.spawnLocation = location; + } + @Override public @Unmodifiable Map<String, ClickAction<?>> getActions() { return Map.copyOf(actions); @@ -104,6 +115,11 @@ public EntityType getType() { return glowColor; } + @Override + public void setGlowColor(@Nullable NamedTextColor color) { + this.glowColor = color; + } + @Override public Optional<T> getEntity() { return Optional.ofNullable(entity).filter(Entity::isValid); @@ -114,6 +130,13 @@ public Pose getPose() { return pose; } + @Override + public void setPose(Pose pose) { + if (pose == this.pose) return; + this.pose = pose; + getEntity().ifPresent(entity -> entity.setPose(pose, true)); + } + @Override public @Unmodifiable Set<UUID> getViewers() { return Set.copyOf(viewers); @@ -183,21 +206,50 @@ public boolean isCollidable() { return collidable; } + @Override + public void setCollidable(boolean collidable) { + if (collidable == this.collidable) return; + this.collidable = collidable; + getEntity().ifPresent(entity -> { + if (!(entity instanceof LivingEntity living)) return; + living.setCollidable(collidable); + }); + } + @Override public boolean isDisplayNameVisible() { return displayNameVisible; } + @Override + public void setDisplayNameVisible(boolean visible) { + if (visible == displayNameVisible) return; + this.displayNameVisible = visible; + getEntity().ifPresent(this::updateDisplayName); + } + @Override public boolean isInvincible() { return invincible; } + @Override + public void setInvincible(boolean invincible) { + if (invincible == this.invincible) return; + this.invincible = invincible; + getEntity().ifPresent(entity -> entity.setInvulnerable(invincible)); + } + @Override public boolean isPersistent() { return persistent; } + @Override + public void setPersistent(boolean persistent) { + this.persistent = persistent; + } + @Override public boolean isSpawned() { return entity != null && entity.isValid(); @@ -208,6 +260,12 @@ public boolean isTicking() { return ticking; } + @Override + public void setTicking(boolean ticking) { + this.ticking = ticking; + // todo: use custom entity impl to make this possible + } + @Override public boolean isTrackedBy(Player player) { return getEntity().map(entity -> entity.getTrackedBy().contains(player)).orElse(false); @@ -223,6 +281,22 @@ public boolean isVisibleByDefault() { return visibleByDefault; } + @Override + public void setVisibleByDefault(boolean visible) { + if (visible == visibleByDefault) return; + this.visibleByDefault = visible; + getEntity().ifPresent(entity -> { + entity.setVisibleByDefault(visible); + if (visible) entity.getTrackedBy().forEach(player -> { + if (isViewer(player.getUniqueId())) return; + player.hideEntity(plugin, entity); + }); + else getViewers().stream().map(plugin.getServer()::getPlayer) + .filter(Objects::nonNull) + .forEach(player -> player.showEntity(plugin, entity)); + }); + } + @Override public boolean persist() { if (!isPersistent()) return false; @@ -296,6 +370,20 @@ public boolean spawn(Location location) { return true; } + @Override + @SuppressWarnings("ResultOfMethodCallIgnored") + public void remove() { + despawn(); + file().delete(); + backupFile().delete(); + plugin.characterController().unregister(name); + } + + @Override + public void setGravity(boolean gravity) { + this.gravity = gravity; + } + protected void preSpawn(T entity) { if (entity instanceof LivingEntity living) { living.setAI(false); @@ -319,100 +407,11 @@ protected void updateDisplayName(T entity) { entity.setCustomNameVisible(displayNameVisible && displayName != null); } - @Override - @SuppressWarnings("ResultOfMethodCallIgnored") - public void remove() { - despawn(); - file().delete(); - backupFile().delete(); - plugin.characterController().unregister(name); - } - - @Override - public void setCollidable(boolean collidable) { - if (collidable == this.collidable) return; - this.collidable = collidable; - getEntity().ifPresent(entity -> { - if (!(entity instanceof LivingEntity living)) return; - living.setCollidable(collidable); - }); - } - - @Override - public void setDisplayName(@Nullable Component displayName) { - if (displayName == this.displayName) return; - this.displayName = displayName; - getEntity().ifPresent(this::updateDisplayName); - } - - @Override - public void setDisplayNameVisible(boolean visible) { - if (visible == displayNameVisible) return; - this.displayNameVisible = visible; - getEntity().ifPresent(this::updateDisplayName); - } - - @Override - public void setGlowColor(@Nullable NamedTextColor color) { - this.glowColor = color; - } - - @Override - public void setGravity(boolean gravity) { - this.gravity = gravity; - } - - @Override - public void setInvincible(boolean invincible) { - if (invincible == this.invincible) return; - this.invincible = invincible; - getEntity().ifPresent(entity -> entity.setInvulnerable(invincible)); - } - - @Override - public void setPersistent(boolean persistent) { - this.persistent = persistent; - } - - @Override - public void setPose(Pose pose) { - if (pose == this.pose) return; - this.pose = pose; - getEntity().ifPresent(entity -> entity.setPose(pose, true)); - } - - @Override - public void setSpawnLocation(@Nullable Location location) { - this.spawnLocation = location; - } - - @Override - public void setTicking(boolean ticking) { - this.ticking = ticking; - // todo: use custom entity impl to make this possible - } - - @Override - public void setVisibleByDefault(boolean visible) { - if (visible == visibleByDefault) return; - this.visibleByDefault = visible; - getEntity().ifPresent(entity -> { - entity.setVisibleByDefault(visible); - if (visible) entity.getTrackedBy().forEach(player -> { - if (isViewer(player.getUniqueId())) return; - player.hideEntity(plugin, entity); - }); - else getViewers().stream().map(plugin.getServer()::getPlayer) - .filter(Objects::nonNull) - .forEach(player -> player.showEntity(plugin, entity)); - }); + private File file() { + return new File(plugin.savesFolder(), this.name + ".dat"); } private File backupFile() { return new File(plugin.savesFolder(), this.name + ".dat_old"); } - - private File file() { - return new File(plugin.savesFolder(), this.name + ".dat"); - } } diff --git a/src/main/java/net/thenextlvl/character/plugin/character/PaperPlayerCharacter.java b/src/main/java/net/thenextlvl/character/plugin/character/PaperPlayerCharacter.java index 27d21f3..670ea82 100644 --- a/src/main/java/net/thenextlvl/character/plugin/character/PaperPlayerCharacter.java +++ b/src/main/java/net/thenextlvl/character/plugin/character/PaperPlayerCharacter.java @@ -49,16 +49,29 @@ @NullMarked public class PaperPlayerCharacter extends PaperCharacter<Player> implements PlayerCharacter { + private final CraftPlayerProfile profile; + private SkinParts skinParts = new PaperSkinPartBuilder().build(); + private boolean listed = false; private boolean realPlayer = false; - private final CraftPlayerProfile profile; + + private @Nullable TextDisplay displayNameHologram; public PaperPlayerCharacter(CharacterPlugin plugin, String name, UUID uuid) { super(plugin, name, EntityType.PLAYER); this.profile = new CraftPlayerProfile(uuid, name); } + @Override + public boolean despawn() { + if (entity == null || !entity.isValid()) return false; + var packet = new ClientboundRemoveEntitiesPacket(entity.getEntityId()); + plugin.getServer().getOnlinePlayers().forEach(player -> sendPacket(player, packet)); + ((CraftPlayer) entity).getHandle().discard(); + return true; + } + @Override public boolean spawn(Location location) { var server = (CraftServer) plugin.getServer(); @@ -124,18 +137,21 @@ public boolean spawn(Location location) { return true; } - private @NotNull ClientInformation createClientInformation() { - return new ClientInformation("en_us", 2, ChatVisiblity.HIDDEN, true, skinParts.getRaw(), HumanoidArm.RIGHT, false, isListed(), ParticleStatus.MINIMAL); + @Override + public void remove() { + plugin.getServer().getOnlinePlayers().forEach(player -> { + var team = player.getScoreboard().getTeam(getUniqueId().toString()); + if (team != null) team.unregister(); + }); + removeDisplayNameHologram(); + super.remove(); } - public void broadcastCharacter() { - getEntity().ifPresent(entity -> { - var handle = ((CraftPlayer) entity).getHandle(); - var packets = new ClientboundBundlePacket(List.of( - createInitializationPacket(handle), createAddPacket(handle) - )); - entity.getWorld().getPlayers().forEach(player -> sendPacket(player, packets)); - }); + @Override + protected void updateDisplayName(Player player) { + updateDisplayNameHologram(player); + plugin.getServer().getOnlinePlayers().forEach(all -> + updateDisplayName(getCharacterSettingsTeam(all))); } public void loadCharacter(Player player) { @@ -149,27 +165,14 @@ public void loadCharacter(Player player) { }); } - private ClientboundAddEntityPacket createAddPacket(ServerPlayer entity) { - return new ClientboundAddEntityPacket(entity.getId(), entity.getUUID(), - entity.getX(), entity.getY(), entity.getZ(), entity.getXRot(), entity.getYRot(), - entity.getType(), 0, entity.getDeltaMovement(), entity.getYHeadRot()); - } - - private ClientboundPlayerInfoUpdatePacket createInitializationPacket(ServerPlayer entity) { - return ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(entity, isListed()); - } - - private void sendPacket(Player player, Packet<?> packet) { - ((CraftPlayer) player).getHandle().connection.send(packet); - } - - @Override - public boolean despawn() { - if (entity == null || !entity.isValid()) return false; - var packet = new ClientboundRemoveEntitiesPacket(entity.getEntityId()); - plugin.getServer().getOnlinePlayers().forEach(player -> sendPacket(player, packet)); - ((CraftPlayer) entity).getHandle().discard(); - return true; + public void broadcastCharacter() { + getEntity().ifPresent(entity -> { + var handle = ((CraftPlayer) entity).getHandle(); + var packets = new ClientboundBundlePacket(List.of( + createInitializationPacket(handle), createAddPacket(handle) + )); + entity.getWorld().getPlayers().forEach(player -> sendPacket(player, packets)); + }); } @Override @@ -189,16 +192,82 @@ public SkinParts getSkinParts() { return skinParts; } + @Override + public void setSkinParts(SkinParts parts) { + if (this.skinParts == parts) return; + this.skinParts = parts; + getEntity().map(player -> ((CraftPlayer) player).getHandle()) + .ifPresent(this::applySkinPartConfig); + } + @Override public UUID getUniqueId() { return Objects.requireNonNull(profile.getId()); } @Override - protected void updateDisplayName(Player player) { - updateDisplayNameHologram(player); - plugin.getServer().getOnlinePlayers().forEach(all -> - updateDisplayName(getCharacterSettingsTeam(all))); + public boolean clearTextures() { + if (!getGameProfile().getProperties().removeIf(property -> + property.getName().equals("textures"))) return false; + update(); + return true; + } + + @Override + public boolean isListed() { + return listed; + } + + @Override + public void setListed(boolean listed) { + if (this.listed == listed) return; + this.listed = listed; + getEntity().ifPresent(entity -> { + ((CraftPlayer) entity).getHandle().updateOptionsNoEvents(createClientInformation()); + var update = ClientboundPlayerInfoUpdatePacket.updateListed(entity.getUniqueId(), listed); + entity.getTrackedBy().forEach(player -> sendPacket(player, update)); + }); + } + + @Override + public boolean isRealPlayer() { + return realPlayer; + } + + @Override + public void setRealPlayer(boolean real) { + this.realPlayer = real; + } + + @Override + public boolean setTextures(String value, @Nullable String signature) { + var previous = getTextures(); + if (previous != null && previous.getValue().equals(value) + && Objects.equals(previous.getSignature(), signature)) return false; + getGameProfile().getProperties().removeIf(property -> property.getName().equals("textures")); + getGameProfile().getProperties().add(new ProfileProperty("textures", value, signature)); + update(); + return true; + } + + private void sendPacket(Player player, Packet<?> packet) { + ((CraftPlayer) player).getHandle().connection.send(packet); + } + + private ClientboundAddEntityPacket createAddPacket(ServerPlayer entity) { + return new ClientboundAddEntityPacket(entity.getId(), entity.getUUID(), + entity.getX(), entity.getY(), entity.getZ(), entity.getXRot(), entity.getYRot(), + entity.getType(), 0, entity.getDeltaMovement(), entity.getYHeadRot()); + } + + private ClientboundPlayerInfoUpdatePacket createInitializationPacket(ServerPlayer entity) { + return ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(entity, isListed()); + } + + private void updateDisplayName(Team team) { + var status = displayNameVisible && displayName == null ? OptionStatus.ALWAYS : OptionStatus.NEVER; + team.setOption(Option.NAME_TAG_VISIBILITY, status); + team.color(glowColor); } private Team getCharacterSettingsTeam(Player player) { @@ -209,13 +278,13 @@ private Team getCharacterSettingsTeam(Player player) { return team; } - private void updateDisplayName(Team team) { - var status = displayNameVisible && displayName == null ? OptionStatus.ALWAYS : OptionStatus.NEVER; - team.setOption(Option.NAME_TAG_VISIBILITY, status); - team.color(glowColor); + private @NotNull ClientInformation createClientInformation() { + return new ClientInformation("en_us", 2, ChatVisiblity.HIDDEN, true, skinParts.getRaw(), HumanoidArm.RIGHT, false, isListed(), ParticleStatus.MINIMAL); } - private @Nullable TextDisplay displayNameHologram; + private void applySkinPartConfig(ServerPlayer player) { + player.getEntityData().set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) getSkinParts().getRaw()); + } private void updateDisplayNameHologram(Player player) { if (displayName == null || !displayNameVisible) { @@ -255,69 +324,6 @@ private void removeDisplayNameHologram() { displayNameHologram = null; } - @Override - public void remove() { - plugin.getServer().getOnlinePlayers().forEach(player -> { - var team = player.getScoreboard().getTeam(getUniqueId().toString()); - if (team != null) team.unregister(); - }); - removeDisplayNameHologram(); - super.remove(); - } - - @Override - public boolean clearTextures() { - if (!getGameProfile().getProperties().removeIf(property -> - property.getName().equals("textures"))) return false; - update(); - return true; - } - - @Override - public boolean isListed() { - return listed; - } - - @Override - public boolean isRealPlayer() { - return realPlayer; - } - - @Override - public boolean setTextures(String value, @Nullable String signature) { - var previous = getTextures(); - if (previous != null && previous.getValue().equals(value) - && Objects.equals(previous.getSignature(), signature)) return false; - getGameProfile().getProperties().removeIf(property -> property.getName().equals("textures")); - getGameProfile().getProperties().add(new ProfileProperty("textures", value, signature)); - update(); - return true; - } - - @Override - public void setListed(boolean listed) { - if (this.listed == listed) return; - this.listed = listed; - getEntity().ifPresent(entity -> { - ((CraftPlayer) entity).getHandle().updateOptionsNoEvents(createClientInformation()); - var update = ClientboundPlayerInfoUpdatePacket.updateListed(entity.getUniqueId(), listed); - entity.getTrackedBy().forEach(player -> sendPacket(player, update)); - }); - } - - @Override - public void setRealPlayer(boolean real) { - this.realPlayer = real; - } - - @Override - public void setSkinParts(SkinParts parts) { - if (this.skinParts == parts) return; - this.skinParts = parts; - getEntity().map(player -> ((CraftPlayer) player).getHandle()) - .ifPresent(this::applySkinPartConfig); - } - private boolean update() { if (entity == null) return false; var handle = ((CraftPlayer) entity).getHandle(); @@ -331,10 +337,6 @@ remove, removeInfo, createInitializationPacket(handle), createAddPacket(handle), return true; } - private void applySkinPartConfig(ServerPlayer player) { - player.getEntityData().set(DATA_PLAYER_MODE_CUSTOMISATION, (byte) getSkinParts().getRaw()); - } - private class CraftCharacter extends CraftPlayer { public CraftCharacter(CraftServer server, ServerPlayer handle) { super(server, handle); @@ -358,4 +360,6 @@ public void setPos(double x, double y, double z) { PaperPlayerCharacter.this.getEntity().ifPresent(PaperPlayerCharacter.this::updateDisplayNameHologram); } } + + } diff --git a/src/main/java/net/thenextlvl/character/plugin/character/PaperSkinPartBuilder.java b/src/main/java/net/thenextlvl/character/plugin/character/PaperSkinPartBuilder.java index b6d64f7..1eaafaf 100644 --- a/src/main/java/net/thenextlvl/character/plugin/character/PaperSkinPartBuilder.java +++ b/src/main/java/net/thenextlvl/character/plugin/character/PaperSkinPartBuilder.java @@ -30,23 +30,23 @@ public SkinPartBuilder cape(boolean enabled) { } @Override - public SkinPartBuilder jacket(boolean enabled) { - return toggle(SkinLayer.JACKET, enabled); + public SkinPartBuilder hat(boolean enabled) { + return toggle(SkinLayer.HAT, enabled); } @Override - public SkinPartBuilder leftSleeve(boolean enabled) { - return toggle(SkinLayer.LEFT_SLEEVE, enabled); + public SkinPartBuilder jacket(boolean enabled) { + return toggle(SkinLayer.JACKET, enabled); } @Override - public SkinPartBuilder rightSleeve(boolean enabled) { - return toggle(SkinLayer.RIGHT_SLEEVE, enabled); + public SkinPartBuilder leftPants(boolean enabled) { + return toggle(SkinLayer.LEFT_PANTS_LEG, enabled); } @Override - public SkinPartBuilder leftPants(boolean enabled) { - return toggle(SkinLayer.LEFT_PANTS_LEG, enabled); + public SkinPartBuilder leftSleeve(boolean enabled) { + return toggle(SkinLayer.LEFT_SLEEVE, enabled); } @Override @@ -55,8 +55,8 @@ public SkinPartBuilder rightPants(boolean enabled) { } @Override - public SkinPartBuilder hat(boolean enabled) { - return toggle(SkinLayer.HAT, enabled); + public SkinPartBuilder rightSleeve(boolean enabled) { + return toggle(SkinLayer.RIGHT_SLEEVE, enabled); } @Override diff --git a/src/main/java/net/thenextlvl/character/plugin/command/CharacterActionPermissionCommand.java b/src/main/java/net/thenextlvl/character/plugin/command/CharacterActionPermissionCommand.java index c37eb8c..fae6eee 100644 --- a/src/main/java/net/thenextlvl/character/plugin/command/CharacterActionPermissionCommand.java +++ b/src/main/java/net/thenextlvl/character/plugin/command/CharacterActionPermissionCommand.java @@ -36,15 +36,6 @@ static LiteralArgumentBuilder<CommandSourceStack> create(CharacterPlugin plugin) .executes(context -> set(context, plugin))); } - private static ArgumentBuilder<CommandSourceStack, ?> permissionArgument() { - return Commands.argument("permission", StringArgumentType.string()); - } - - private static int set(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) { - var permission = context.getArgument("permission", String.class); - return set(context, permission, plugin); - } - private static int set(CommandContext<CommandSourceStack> context, @Nullable String permission, CharacterPlugin plugin) { var sender = context.getSource().getSender(); var character = context.getArgument("character", Character.class); @@ -70,4 +61,13 @@ private static int set(CommandContext<CommandSourceStack> context, @Nullable Str Placeholder.unparsed("permission", String.valueOf(permission))); return success ? Command.SINGLE_SUCCESS : 0; } + + private static ArgumentBuilder<CommandSourceStack, ?> permissionArgument() { + return Commands.argument("permission", StringArgumentType.string()); + } + + private static int set(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) { + var permission = context.getArgument("permission", String.class); + return set(context, permission, plugin); + } } diff --git a/src/main/java/net/thenextlvl/character/plugin/command/CharacterSkinCommand.java b/src/main/java/net/thenextlvl/character/plugin/command/CharacterSkinCommand.java index 3edc71b..180b519 100644 --- a/src/main/java/net/thenextlvl/character/plugin/command/CharacterSkinCommand.java +++ b/src/main/java/net/thenextlvl/character/plugin/command/CharacterSkinCommand.java @@ -36,22 +36,12 @@ static LiteralArgumentBuilder<CommandSourceStack> create(CharacterPlugin plugin) .then(set(plugin)); } - private static ArgumentBuilder<CommandSourceStack, ?> layer(CharacterPlugin plugin) { return Commands.literal("layer") .then(layer("hide", plugin, false)) .then(layer("show", plugin, true)); } - private static LiteralArgumentBuilder<CommandSourceStack> layer(String name, CharacterPlugin plugin, boolean visible) { - return Commands.literal(name).then(layerArgument(plugin).then(playerCharacterArgument(plugin) - .executes(context -> layerToggle(context, plugin, visible)))); - } - - private static ArgumentBuilder<CommandSourceStack, ?> layerArgument(CharacterPlugin plugin) { - return Commands.argument("layer", new EnumArgument<>(SkinLayer.class)); - } - private static ArgumentBuilder<CommandSourceStack, ?> reset(CharacterPlugin plugin) { return Commands.literal("reset").then(playerCharacterArgument(plugin) .executes(context -> setSkin(context, null, plugin))); @@ -64,6 +54,22 @@ private static LiteralArgumentBuilder<CommandSourceStack> layer(String name, Cha .then(urlSkinArgument(plugin))); } + private static LiteralArgumentBuilder<CommandSourceStack> layer(String name, CharacterPlugin plugin, boolean visible) { + return Commands.literal(name).then(layerArgument(plugin).then(playerCharacterArgument(plugin) + .executes(context -> layerToggle(context, plugin, visible)))); + } + + private static int setSkin(CommandContext<CommandSourceStack> context, @Nullable ProfileProperty textures, CharacterPlugin plugin) { + var sender = context.getSource().getSender(); + var character = context.getArgument("character", PlayerCharacter.class); + + var success = textures == null ? character.clearTextures() + : character.setTextures(textures.getValue(), textures.getSignature()); + var message = success ? "character.skin" : "nothing.changed"; + plugin.bundle().sendMessage(sender, message, Placeholder.unparsed("character", character.getName())); + return success ? Command.SINGLE_SUCCESS : 0; + } + private static ArgumentBuilder<CommandSourceStack, ?> fileSkinArgument(CharacterPlugin plugin) { return Commands.literal("file").then(Commands.argument("file", StringArgumentType.string()) .then(Commands.literal("slim").executes(context -> setFileSkin(context, true, plugin))) @@ -84,6 +90,35 @@ private static LiteralArgumentBuilder<CommandSourceStack> layer(String name, Cha .executes(context -> setUrlSkin(context, false, plugin))); } + private static ArgumentBuilder<CommandSourceStack, ?> layerArgument(CharacterPlugin plugin) { + return Commands.argument("layer", new EnumArgument<>(SkinLayer.class)); + } + + private static int layerToggle(CommandContext<CommandSourceStack> context, CharacterPlugin plugin, boolean visible) { + var sender = context.getSource().getSender(); + var character = context.getArgument("character", PlayerCharacter.class); + + var layer = context.getArgument("layer", SkinLayer.class); + var skinParts = plugin.characterProvider() + .skinPartBuilder(character.getSkinParts()) + .toggle(layer, visible) + .build(); + + if (skinParts.equals(character.getSkinParts())) { + plugin.bundle().sendMessage(sender, "nothing.changed"); + return 0; + } + + character.setSkinParts(skinParts); + + var message = visible ? "character.skin_layer.shown" : "character.skin_layer.hidden"; + plugin.bundle().sendMessage(sender, message, + Placeholder.component("layer", Component.translatable(layer)), + Placeholder.unparsed("character", character.getName())); + + return Command.SINGLE_SUCCESS; + } + private static int setFileSkin(CommandContext<CommandSourceStack> context, boolean slim, CharacterPlugin plugin) { var sender = context.getSource().getSender(); var file = new File(context.getArgument("file", String.class)); @@ -149,40 +184,4 @@ private static int setUrlSkin(CommandContext<CommandSourceStack> context, boolea return 0; } } - - private static int layerToggle(CommandContext<CommandSourceStack> context, CharacterPlugin plugin, boolean visible) { - var sender = context.getSource().getSender(); - var character = context.getArgument("character", PlayerCharacter.class); - - var layer = context.getArgument("layer", SkinLayer.class); - var skinParts = plugin.characterProvider() - .skinPartBuilder(character.getSkinParts()) - .toggle(layer, visible) - .build(); - - if (skinParts.equals(character.getSkinParts())) { - plugin.bundle().sendMessage(sender, "nothing.changed"); - return 0; - } - - character.setSkinParts(skinParts); - - var message = visible ? "character.skin_layer.shown" : "character.skin_layer.hidden"; - plugin.bundle().sendMessage(sender, message, - Placeholder.component("layer", Component.translatable(layer)), - Placeholder.unparsed("character", character.getName())); - - return Command.SINGLE_SUCCESS; - } - - private static int setSkin(CommandContext<CommandSourceStack> context, @Nullable ProfileProperty textures, CharacterPlugin plugin) { - var sender = context.getSource().getSender(); - var character = context.getArgument("character", PlayerCharacter.class); - - var success = textures == null ? character.clearTextures() - : character.setTextures(textures.getValue(), textures.getSignature()); - var message = success ? "character.skin" : "nothing.changed"; - plugin.bundle().sendMessage(sender, message, Placeholder.unparsed("character", character.getName())); - return success ? Command.SINGLE_SUCCESS : 0; - } } diff --git a/src/main/java/net/thenextlvl/character/plugin/command/CharacterTagCommand.java b/src/main/java/net/thenextlvl/character/plugin/command/CharacterTagCommand.java index 118fbe7..4977472 100644 --- a/src/main/java/net/thenextlvl/character/plugin/command/CharacterTagCommand.java +++ b/src/main/java/net/thenextlvl/character/plugin/command/CharacterTagCommand.java @@ -27,16 +27,16 @@ static LiteralArgumentBuilder<CommandSourceStack> create(CharacterPlugin plugin) .then(show(plugin)); } - private static ArgumentBuilder<CommandSourceStack, ?> reset(CharacterPlugin plugin) { - return Commands.literal("reset").then(characterArgument(plugin) - .executes(context -> reset(context, plugin))); - } - private static ArgumentBuilder<CommandSourceStack, ?> hide(CharacterPlugin plugin) { return Commands.literal("hide").then(characterArgument(plugin) .executes(context -> toggle(context, plugin, false))); } + private static ArgumentBuilder<CommandSourceStack, ?> reset(CharacterPlugin plugin) { + return Commands.literal("reset").then(characterArgument(plugin) + .executes(context -> reset(context, plugin))); + } + private static ArgumentBuilder<CommandSourceStack, ?> set(CharacterPlugin plugin) { return Commands.literal("set").then(characterArgument(plugin) .then(tagArgument(plugin).executes(context -> set(context, plugin)))); @@ -47,26 +47,17 @@ static LiteralArgumentBuilder<CommandSourceStack> create(CharacterPlugin plugin) .executes(context -> toggle(context, plugin, true))); } - private static ArgumentBuilder<CommandSourceStack, ?> tagArgument(CharacterPlugin plugin) { - return Commands.argument("tag", StringArgumentType.greedyString()); - } - - private static int set(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) { + private static int toggle(CommandContext<CommandSourceStack> context, CharacterPlugin plugin, boolean visible) { var sender = context.getSource().getSender(); var character = context.getArgument("character", Character.class); - var tag = context.getArgument("tag", String.class); - var displayName = MiniMessage.miniMessage().deserialize(tag); - if (Objects.equals(character.getDisplayName(), displayName)) { - plugin.bundle().sendMessage(sender, "nothing.changed"); - return 0; - } + var success = character.isDisplayNameVisible() != visible; + var message = !success ? "nothing.changed" : visible ? "character.tag.shown" : "character.tag.hidden"; - character.setDisplayName(displayName); - plugin.bundle().sendMessage(sender, "character.tag.set", - Placeholder.unparsed("character", character.getName()), - Placeholder.component("tag", displayName)); - return Command.SINGLE_SUCCESS; + if (success) character.setDisplayNameVisible(visible); + plugin.bundle().sendMessage(sender, message, Placeholder.unparsed("character", character.getName())); + + return success ? Command.SINGLE_SUCCESS : 0; } private static int reset(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) { @@ -84,16 +75,25 @@ private static int reset(CommandContext<CommandSourceStack> context, CharacterPl return Command.SINGLE_SUCCESS; } - private static int toggle(CommandContext<CommandSourceStack> context, CharacterPlugin plugin, boolean visible) { + private static ArgumentBuilder<CommandSourceStack, ?> tagArgument(CharacterPlugin plugin) { + return Commands.argument("tag", StringArgumentType.greedyString()); + } + + private static int set(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) { var sender = context.getSource().getSender(); var character = context.getArgument("character", Character.class); + var tag = context.getArgument("tag", String.class); + var displayName = MiniMessage.miniMessage().deserialize(tag); - var success = character.isDisplayNameVisible() != visible; - var message = !success ? "nothing.changed" : visible ? "character.tag.shown" : "character.tag.hidden"; - - if (success) character.setDisplayNameVisible(visible); - plugin.bundle().sendMessage(sender, message, Placeholder.unparsed("character", character.getName())); + if (Objects.equals(character.getDisplayName(), displayName)) { + plugin.bundle().sendMessage(sender, "nothing.changed"); + return 0; + } - return success ? Command.SINGLE_SUCCESS : 0; + character.setDisplayName(displayName); + plugin.bundle().sendMessage(sender, "character.tag.set", + Placeholder.unparsed("character", character.getName()), + Placeholder.component("tag", displayName)); + return Command.SINGLE_SUCCESS; } } diff --git a/src/main/java/net/thenextlvl/character/plugin/command/CharacterTeleportCommand.java b/src/main/java/net/thenextlvl/character/plugin/command/CharacterTeleportCommand.java index 6dff4bb..5d78e2b 100644 --- a/src/main/java/net/thenextlvl/character/plugin/command/CharacterTeleportCommand.java +++ b/src/main/java/net/thenextlvl/character/plugin/command/CharacterTeleportCommand.java @@ -32,26 +32,6 @@ static LiteralArgumentBuilder<CommandSourceStack> create(CharacterPlugin plugin) return Commands.literal("teleport").then(teleport); } - private static ArgumentBuilder<CommandSourceStack, ?> entityArgument(CharacterPlugin plugin) { - return Commands.argument("entity", ArgumentTypes.entity()); - } - - private static ArgumentBuilder<CommandSourceStack, ?> positionArgument(CharacterPlugin plugin) { - return Commands.argument("position", ArgumentTypes.finePosition(true)); - } - - private static int teleportEntity(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) throws CommandSyntaxException { - var selector = context.getArgument("entity", EntitySelectorArgumentResolver.class); - var entity = selector.resolve(context.getSource()).getFirst(); - return teleport(context, plugin, entity.getLocation()); - } - - private static int teleportPosition(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) throws CommandSyntaxException { - var resolver = context.getArgument("position", FinePositionResolver.class); - var position = resolver.resolve(context.getSource()).toLocation(context.getSource().getLocation().getWorld()); - return teleport(context, plugin, position); - } - private static int teleportSelf(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) { var sender = context.getSource().getSender(); @@ -70,6 +50,26 @@ private static int teleportSelf(CommandContext<CommandSourceStack> context, Char return Command.SINGLE_SUCCESS; } + private static ArgumentBuilder<CommandSourceStack, ?> positionArgument(CharacterPlugin plugin) { + return Commands.argument("position", ArgumentTypes.finePosition(true)); + } + + private static int teleportPosition(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) throws CommandSyntaxException { + var resolver = context.getArgument("position", FinePositionResolver.class); + var position = resolver.resolve(context.getSource()).toLocation(context.getSource().getLocation().getWorld()); + return teleport(context, plugin, position); + } + + private static ArgumentBuilder<CommandSourceStack, ?> entityArgument(CharacterPlugin plugin) { + return Commands.argument("entity", ArgumentTypes.entity()); + } + + private static int teleportEntity(CommandContext<CommandSourceStack> context, CharacterPlugin plugin) throws CommandSyntaxException { + var selector = context.getArgument("entity", EntitySelectorArgumentResolver.class); + var entity = selector.resolve(context.getSource()).getFirst(); + return teleport(context, plugin, entity.getLocation()); + } + private static int teleport(CommandContext<CommandSourceStack> context, CharacterPlugin plugin, Location location) { var sender = context.getSource().getSender(); var character = (Character<?>) context.getArgument("character", Character.class); diff --git a/src/main/java/net/thenextlvl/character/plugin/command/suggestion/CharacterWithActionSuggestionProvider.java b/src/main/java/net/thenextlvl/character/plugin/command/suggestion/CharacterWithActionSuggestionProvider.java index 35ee782..c492458 100644 --- a/src/main/java/net/thenextlvl/character/plugin/command/suggestion/CharacterWithActionSuggestionProvider.java +++ b/src/main/java/net/thenextlvl/character/plugin/command/suggestion/CharacterWithActionSuggestionProvider.java @@ -18,11 +18,11 @@ public CharacterWithActionSuggestionProvider(CharacterPlugin plugin) { @Override public CompletableFuture<Suggestions> getSuggestions(CommandContext<T> context, SuggestionsBuilder builder) { - plugin.characterController().getCharacters().stream() - .filter(character -> !character.getActions().isEmpty()) - .map(Character::getName) - .filter(name -> name.toLowerCase().contains(builder.getRemainingLowerCase())) - .forEach(builder::suggest); - return builder.buildFuture(); + plugin.characterController().getCharacters().stream() + .filter(character -> !character.getActions().isEmpty()) + .map(Character::getName) + .filter(name -> name.toLowerCase().contains(builder.getRemainingLowerCase())) + .forEach(builder::suggest); + return builder.buildFuture(); } } diff --git a/src/main/java/net/thenextlvl/character/plugin/listener/ConnectionListener.java b/src/main/java/net/thenextlvl/character/plugin/listener/ConnectionListener.java index 7f2ecea..a0b5125 100644 --- a/src/main/java/net/thenextlvl/character/plugin/listener/ConnectionListener.java +++ b/src/main/java/net/thenextlvl/character/plugin/listener/ConnectionListener.java @@ -21,6 +21,11 @@ public ConnectionListener(CharacterPlugin plugin) { this.plugin = plugin; } + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { + loadCharacters(event.getPlayer().getWorld(), event.getPlayer()); + } + @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event) { loadCharacters(event.getPlayer().getWorld(), event.getPlayer()); @@ -33,11 +38,6 @@ public void onPlayerQuit(PlayerQuitEvent event) { action.resetCooldown(event.getPlayer()))); } - @EventHandler(priority = EventPriority.MONITOR) - public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { - loadCharacters(event.getPlayer().getWorld(), event.getPlayer()); - } - private void loadCharacters(World world, Player player) { plugin.characterController().getCharacters(world).stream() .filter(character -> character.getType().equals(EntityType.PLAYER)) diff --git a/src/main/java/net/thenextlvl/character/plugin/network/EmptyChannel.java b/src/main/java/net/thenextlvl/character/plugin/network/EmptyChannel.java index dd082bd..7224b38 100644 --- a/src/main/java/net/thenextlvl/character/plugin/network/EmptyChannel.java +++ b/src/main/java/net/thenextlvl/character/plugin/network/EmptyChannel.java @@ -17,63 +17,63 @@ public EmptyChannel() { } @Override - protected AbstractUnsafe newUnsafe() { - return null; + public ChannelConfig config() { + config.setAutoRead(true); + return config; } @Override - protected boolean isCompatible(EventLoop eventLoop) { + public boolean isOpen() { return false; } @Override - protected SocketAddress localAddress0() { - return null; + public boolean isActive() { + return false; } @Override - protected SocketAddress remoteAddress0() { - return null; + public ChannelMetadata metadata() { + return new ChannelMetadata(true); } @Override - protected void doBind(SocketAddress socketAddress) { + protected AbstractUnsafe newUnsafe() { + return null; } @Override - protected void doDisconnect() { + protected boolean isCompatible(EventLoop eventLoop) { + return false; } @Override - protected void doClose() { + protected SocketAddress localAddress0() { + return null; } @Override - protected void doBeginRead() { + protected SocketAddress remoteAddress0() { + return null; } @Override - protected void doWrite(ChannelOutboundBuffer channelOutboundBuffer) { + protected void doBind(SocketAddress socketAddress) { } @Override - public ChannelConfig config() { - config.setAutoRead(true); - return config; + protected void doDisconnect() { } @Override - public boolean isOpen() { - return false; + protected void doClose() { } @Override - public boolean isActive() { - return false; + protected void doBeginRead() { } @Override - public ChannelMetadata metadata() { - return new ChannelMetadata(true); + protected void doWrite(ChannelOutboundBuffer channelOutboundBuffer) { } } diff --git a/src/main/java/net/thenextlvl/character/plugin/network/EmptyConnection.java b/src/main/java/net/thenextlvl/character/plugin/network/EmptyConnection.java index db09264..344db97 100644 --- a/src/main/java/net/thenextlvl/character/plugin/network/EmptyConnection.java +++ b/src/main/java/net/thenextlvl/character/plugin/network/EmptyConnection.java @@ -26,34 +26,34 @@ public <T extends PacketListener> void setupInboundProtocol(ProtocolInfo<T> prot } @Override - public void flushChannel() { + public void setListenerForServerboundHandshake(PacketListener packetListener) { + super.setListenerForServerboundHandshake(packetListener); + handleDisconnection(); } @Override - public boolean isConnected() { - return true; + public void send(Packet<?> packet) { } @Override - public boolean isConnecting() { - return false; + public void send(Packet<?> packet, @Nullable PacketSendListener sendListener) { } @Override - public void send(Packet<?> packet) { + public void send(Packet<?> packet, @Nullable PacketSendListener listener, boolean flush) { } @Override - public void send(Packet<?> packet, @Nullable PacketSendListener sendListener) { + public void flushChannel() { } @Override - public void send(Packet<?> packet, @Nullable PacketSendListener listener, boolean flush) { + public boolean isConnected() { + return true; } @Override - public void setListenerForServerboundHandshake(PacketListener packetListener) { - super.setListenerForServerboundHandshake(packetListener); - handleDisconnection(); + public boolean isConnecting() { + return false; } } diff --git a/src/main/java/net/thenextlvl/character/plugin/serialization/CharacterSerializer.java b/src/main/java/net/thenextlvl/character/plugin/serialization/CharacterSerializer.java index 051ddbf..34d1fc2 100644 --- a/src/main/java/net/thenextlvl/character/plugin/serialization/CharacterSerializer.java +++ b/src/main/java/net/thenextlvl/character/plugin/serialization/CharacterSerializer.java @@ -15,10 +15,8 @@ public class CharacterSerializer implements TagSerializer<Character<?>> { public CompoundTag serialize(Character<?> character, TagSerializationContext context) throws ParserException { var tag = new CompoundTag(); tag.add("type", context.serialize(character.getType())); - if (character.getDisplayName() != null) - tag.add("displayName", context.serialize(character.getDisplayName())); - if (character.getSpawnLocation() != null) - tag.add("location", context.serialize(character.getSpawnLocation())); + if (character.getDisplayName() != null) tag.add("displayName", context.serialize(character.getDisplayName())); + if (character.getSpawnLocation() != null) tag.add("location", context.serialize(character.getSpawnLocation())); tag.add("collidable", character.isCollidable()); tag.add("displayNameVisible", character.isDisplayNameVisible()); tag.add("gravity", character.hasGravity()); @@ -36,8 +34,7 @@ private CompoundTag serialize(CompoundTag tag, PlayerCharacter character, TagSer if (character.getGameProfile().getId() != null) tag.add("uuid", context.serialize(character.getGameProfile().getId())); var properties = new ListTag<>(CompoundTag.ID); - character.getGameProfile().getProperties().forEach(property -> - properties.add(context.serialize(property))); + character.getGameProfile().getProperties().forEach(property -> properties.add(context.serialize(property))); tag.add("listed", character.isListed()); tag.add("properties", properties); tag.add("realPlayer", character.isRealPlayer());