From 7382f39ce077c9aa36e2e202537d18f3a6ce86ce Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Tue, 29 Jan 2019 20:12:52 +0300 Subject: [PATCH 01/13] Create PlayerControl --- .../commons/control/PlayerControl.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java new file mode 100644 index 000000000..51bf41eee --- /dev/null +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java @@ -0,0 +1,37 @@ +package ru.progrm_jarvis.minecraft.commons.control; + +import org.bukkit.entity.Player; + +/** + * An object which manages the player + */ +public interface PlayerControl { + + /** + * Starts the new control session for the player. + * + * @param player player for whom to start the control session + * @return created control session for the player (or the one he currently has in this player control) + * + * @apiNote the session should be ended using {@link S#end()} + */ + S startSession(final Player player); + + /** + * Session of player control, responsible for handling the player's controls + */ + interface Session { + + /** + * Gets the player manages by this control session. + * + * @return MANAGED PLAYER + */ + Player getPlayer(); + + /** + * Ends this player control session. + */ + void end(); + } +} From 061b20e9cda987ef9a717997528b8bb3e6b7f18b Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Tue, 29 Jan 2019 20:20:24 +0300 Subject: [PATCH 02/13] Rename PlayerControl to PlayerControls and implement PlayerContainer --- .../commons/control/PlayerControl.java | 37 ------------------ .../commons/control/PlayerControls.java | 38 +++++++++++++++++++ 2 files changed, 38 insertions(+), 37 deletions(-) delete mode 100644 commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java create mode 100644 commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java deleted file mode 100644 index 51bf41eee..000000000 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControl.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.progrm_jarvis.minecraft.commons.control; - -import org.bukkit.entity.Player; - -/** - * An object which manages the player - */ -public interface PlayerControl { - - /** - * Starts the new control session for the player. - * - * @param player player for whom to start the control session - * @return created control session for the player (or the one he currently has in this player control) - * - * @apiNote the session should be ended using {@link S#end()} - */ - S startSession(final Player player); - - /** - * Session of player control, responsible for handling the player's controls - */ - interface Session { - - /** - * Gets the player manages by this control session. - * - * @return MANAGED PLAYER - */ - Player getPlayer(); - - /** - * Ends this player control session. - */ - void end(); - } -} diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java new file mode 100644 index 000000000..2cbdc3c1c --- /dev/null +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java @@ -0,0 +1,38 @@ +package ru.progrm_jarvis.minecraft.commons.control; + +import org.bukkit.entity.Player; +import ru.progrm_jarvis.minecraft.commons.player.collection.PlayerContainer; + +/** + * An object which manages the player + */ +public interface PlayerControls extends PlayerContainer { + + /** + * Starts the new controls session for the player. + * + * @param player player for whom to start the controls session + * @return created controls session for the player (or the one he currently has in this player controls) + * + * @apiNote the session should be ended using {@link S#end()} + */ + S startSession(final Player player); + + /** + * Session of player controls, responsible for handling the player's controls + */ + interface Session { + + /** + * Gets the player manages by this controls session. + * + * @return MANAGED PLAYER + */ + Player getPlayer(); + + /** + * Ends this player controls session. + */ + void end(); + } +} From ea8f0aa323f2ef3450255d63688e3093722d60f3 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Tue, 29 Jan 2019 20:26:34 +0300 Subject: [PATCH 03/13] Organize add/remove operations in PlayerControls --- .../commons/control/PlayerControls.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java index 2cbdc3c1c..0e5416380 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java @@ -1,8 +1,11 @@ package ru.progrm_jarvis.minecraft.commons.control; +import lombok.NonNull; import org.bukkit.entity.Player; import ru.progrm_jarvis.minecraft.commons.player.collection.PlayerContainer; +import java.util.Optional; + /** * An object which manages the player */ @@ -16,7 +19,25 @@ public interface PlayerControls extends Player * * @apiNote the session should be ended using {@link S#end()} */ - S startSession(final Player player); + S startSession(Player player); + + @Override + default void addPlayer(@NonNull final Player player) { + startSession(player); + } + + /** + * Gets the current controls session of the specified player. + * + * @param player player for whom to get the controls sessions + * @return optional of the player's current controls session or empty if it doesn't have one + */ + Optional getSession(Player player); + + @Override + default void removePlayer(@NonNull final Player player) { + getSession(player).ifPresent(Session::end); + } /** * Session of player controls, responsible for handling the player's controls From fbe6ca2c96cbc1160edc287a16a589386e3f2cc7 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Tue, 29 Jan 2019 20:28:39 +0300 Subject: [PATCH 04/13] Implement default PlayerControls#containsPlayer(Player) --- .../minecraft/commons/control/PlayerControls.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java index 0e5416380..d900cb9f9 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java @@ -39,6 +39,11 @@ default void removePlayer(@NonNull final Player player) { getSession(player).ifPresent(Session::end); } + @Override + default boolean containsPlayer(@NonNull final Player player) { + return getSession(player).isPresent(); + } + /** * Session of player controls, responsible for handling the player's controls */ From da5602b491b3004f0a4137938139b4a572d0818e Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 17:47:55 +0300 Subject: [PATCH 05/13] Add AbstractPlayerControls --- .../control/AbstractPlayerControls.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java new file mode 100644 index 000000000..a831ed837 --- /dev/null +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -0,0 +1,96 @@ +package ru.progrm_jarvis.minecraft.commons.control; + +import lombok.*; +import lombok.experimental.FieldDefaults; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.Map; + +/** + * Abstract implementation of {@link PlayerControls} providing its common mechanisms. + */ +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) +public abstract class AbstractPlayerControls implements PlayerControls { + + /** + * Map of player's currently managed by this player controls and their current active sessions + */ + Map sessions; + + /** + * Whether this control session is a global player container or not + */ + boolean global; + + // a more optimal solution without allocating unneeded Optional objects + @Override + public boolean containsPlayer(@NonNull final Player player) { + return sessions.containsKey(player); + } + + // a more optimal solution without allocating unneeded Optional objects + @Override + public void removePlayer(@NonNull final Player player) { + val session = sessions.get(player); + if (session != null) session.end(); + } + + @Override + public Collection getPlayers() { + return sessions.keySet(); + } + + @Override + public S startSession(@NonNull final Player player) { + val session = createSession(player); + sessions.put(player, session); + + return session; + } + + /** + * Creates the controls session for the player specified. + * + * @param player player for whom to initialize the controls session + * @return created controls session + * + * @implSpec implementations are not required to add the created session to {@link #sessions} + * as this is done by this method's caller + * + * @see Session#startSession(Player) this method's default caller + */ + protected abstract S createSession(Player player); + + /** + * Finalizer called in {@link S#end()} in order to cleanup everything needed when the player end his session. + * + * @param session session to release + * @implSpec should not call to {@link S#end()} as this will (most definitely) lead to infinite recursion + * + * @implSpec implementations are not required to remove the session from {@link #sessions} + * as this is done by this method's caller + * + * @see Session#end() this method's default caller + */ + protected abstract void releaseControls(S session); + + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) + protected abstract class Session implements PlayerControls.Session { + + @Getter Player player; + + @Override + public void end() { + //noinspection unchecked + releaseControls((S) this); + sessions.remove(player); + } + } +} From e862e82a645e8468e3a2547086dc971d01e7db22 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 17:53:40 +0300 Subject: [PATCH 06/13] Add null-check annotations to PlayerControls and its implementation --- .../minecraft/commons/control/AbstractPlayerControls.java | 6 +++--- .../minecraft/commons/control/PlayerControls.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index a831ed837..4c8970b96 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -19,7 +19,7 @@ public abstract class AbstractPlayerControls sessions; + @NonNull Map sessions; /** * Whether this control session is a global player container or not @@ -45,7 +45,7 @@ public Collection getPlayers() { } @Override - public S startSession(@NonNull final Player player) { + @NonNull public S startSession(@NonNull final Player player) { val session = createSession(player); sessions.put(player, session); @@ -63,7 +63,7 @@ public S startSession(@NonNull final Player player) { * * @see Session#startSession(Player) this method's default caller */ - protected abstract S createSession(Player player); + @NonNull protected abstract S createSession(Player player); /** * Finalizer called in {@link S#end()} in order to cleanup everything needed when the player end his session. diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java index d900cb9f9..963e68b1a 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java @@ -19,7 +19,7 @@ public interface PlayerControls extends Player * * @apiNote the session should be ended using {@link S#end()} */ - S startSession(Player player); + @NonNull S startSession(@NonNull Player player); @Override default void addPlayer(@NonNull final Player player) { @@ -32,7 +32,7 @@ default void addPlayer(@NonNull final Player player) { * @param player player for whom to get the controls sessions * @return optional of the player's current controls session or empty if it doesn't have one */ - Optional getSession(Player player); + @NonNull Optional getSession(@NonNull Player player); @Override default void removePlayer(@NonNull final Player player) { From d4619fea93459e126a2f8176d11f45ad52072512 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 17:56:44 +0300 Subject: [PATCH 07/13] Add getter for `global` field in AbstractPlayerControls --- .../minecraft/commons/control/AbstractPlayerControls.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index 4c8970b96..644215709 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -24,7 +24,7 @@ public abstract class AbstractPlayerControlsglobal player container or not */ - boolean global; + @Getter boolean global; // a more optimal solution without allocating unneeded Optional objects @Override From 597fb2b79a4121bfc6917a9f5fe64aac7bd1e5e1 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 17:57:59 +0300 Subject: [PATCH 08/13] Make AbstractPlayerControls.Session constructor protected --- .../minecraft/commons/control/AbstractPlayerControls.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index 644215709..7609bf883 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -80,7 +80,7 @@ public Collection getPlayers() { @ToString @EqualsAndHashCode - @RequiredArgsConstructor + @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) protected abstract class Session implements PlayerControls.Session { From d3df1de5e137a1241fb8376d8737f1842a3b45dc Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 17:59:52 +0300 Subject: [PATCH 09/13] Mark Player-key in AbstractPlayerControls#sessions as non-null --- .../minecraft/commons/control/AbstractPlayerControls.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index 7609bf883..5dc24fb7a 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -19,7 +19,7 @@ public abstract class AbstractPlayerControls sessions; + @NonNull Map<@NonNull Player, @NonNull S> sessions; /** * Whether this control session is a global player container or not From f5b5474e2b4c73c6c1d46afc3d16ff6fa6b72126 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 18:10:31 +0300 Subject: [PATCH 10/13] Add docs to AbstractPlayerControls#Session --- .../minecraft/commons/control/AbstractPlayerControls.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index 5dc24fb7a..90597abbd 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -78,12 +78,18 @@ public Collection getPlayers() { */ protected abstract void releaseControls(S session); + /** + * Default session object to be used with {@link AbstractPlayerControls}. + */ @ToString @EqualsAndHashCode @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) protected abstract class Session implements PlayerControls.Session { + /** + * Player whose session this one is + */ @Getter Player player; @Override From 9a4876274f206fd1be2662381185c55901e7b122 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 18:48:08 +0300 Subject: [PATCH 11/13] Expand PlayerControls and its abstract implementation --- .../control/AbstractPlayerControls.java | 45 +++++++++++++++++-- .../commons/control/PlayerControls.java | 25 ++++++++++- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index 90597abbd..89bc21f7c 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -3,9 +3,14 @@ import lombok.*; import lombok.experimental.FieldDefaults; import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import javax.annotation.Nullable; import java.util.Collection; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; /** * Abstract implementation of {@link PlayerControls} providing its common mechanisms. @@ -14,18 +19,34 @@ @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) -public abstract class AbstractPlayerControls implements PlayerControls { +public abstract class AbstractPlayerControls

+ implements PlayerControls { /** - * Map of player's currently managed by this player controls and their current active sessions + * Plugin whose player controls those are. */ - @NonNull Map<@NonNull Player, @NonNull S> sessions; + @NonNull P plugin; /** * Whether this control session is a global player container or not */ @Getter boolean global; + /** + * Map of player's currently managed by this player controls and their current active sessions + */ + @NonNull Map<@NonNull Player, @NonNull S> sessions; + + /** + * Reference to the currently set event handler of this player controls + */ + @NonNull AtomicReference> eventHandler = new AtomicReference<>(); + + @Override + public P getBukkitPlugin() { + return plugin; + } + // a more optimal solution without allocating unneeded Optional objects @Override public boolean containsPlayer(@NonNull final Player player) { @@ -52,6 +73,11 @@ public Collection getPlayers() { return session; } + @Override + public @NonNull Optional getSession(@NonNull final Player player) { + return Optional.ofNullable(sessions.get(player)); + } + /** * Creates the controls session for the player specified. * @@ -76,7 +102,18 @@ public Collection getPlayers() { * * @see Session#end() this method's default caller */ - protected abstract void releaseControls(S session); + protected void releaseControls(@NonNull final S session) {} + + @Override + public void subscribe(@NonNull final Consumer eventHandler) { + this.eventHandler.set(eventHandler); + } + + @Nullable + @Override + public Consumer unsubscribe() { + return eventHandler.getAndSet(null); + } /** * Default session object to be used with {@link AbstractPlayerControls}. diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java index 963e68b1a..6be373342 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/PlayerControls.java @@ -2,14 +2,23 @@ import lombok.NonNull; import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; import ru.progrm_jarvis.minecraft.commons.player.collection.PlayerContainer; +import ru.progrm_jarvis.minecraft.commons.plugin.BukkitPluginContainer; +import javax.annotation.Nullable; import java.util.Optional; +import java.util.function.Consumer; /** * An object which manages the player + * + * @param

type of plugin owning this player controls + * @param type of session created for player whose controls are managed + * @param tye of event to be called by the controls manager */ -public interface PlayerControls extends PlayerContainer { +public interface PlayerControls

+ extends BukkitPluginContainer

, PlayerContainer { /** * Starts the new controls session for the player. @@ -44,6 +53,20 @@ default boolean containsPlayer(@NonNull final Player player) { return getSession(player).isPresent(); } + /** + * Subscribes the event handler on this player controls' events. + * + * @param eventHandler event handler to be used whenever an event is fired + */ + void subscribe(@NonNull Consumer eventHandler); + + /** + * Unsubscribes the current event handler from this player controls' events. + * + * @return event handler which was unsubscribed or {@code null} if there was no subscribed event handler + */ + @Nullable Consumer unsubscribe(); + /** * Session of player controls, responsible for handling the player's controls */ From 0961353ae1aff639ef3727dbbf6b38edbceb0532 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 18:48:21 +0300 Subject: [PATCH 12/13] Add ScrollPlayerControls --- .../control/common/ScrollPlayerControls.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/common/ScrollPlayerControls.java diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/common/ScrollPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/common/ScrollPlayerControls.java new file mode 100644 index 000000000..09f738bf9 --- /dev/null +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/common/ScrollPlayerControls.java @@ -0,0 +1,113 @@ +package ru.progrm_jarvis.minecraft.commons.control.common; + +import com.comphenix.packetwrapper.WrapperPlayClientHeldItemSlot; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import lombok.AccessLevel; +import lombok.NonNull; +import lombok.Value; +import lombok.experimental.FieldDefaults; +import lombok.val; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.Plugin; +import ru.progrm_jarvis.minecraft.commons.control.AbstractPlayerControls; + +import javax.annotation.Nonnull; +import java.util.Map; +import java.util.Optional; + +/** + * Player Controls using the player's hotbar scrolling + */ +public class ScrollPlayerControls

+ extends AbstractPlayerControls { + + public ScrollPlayerControls(@NonNull final P plugin, final boolean global, + @NonNull final Map<@NonNull Player, @NonNull ScrollPlayerControls.Session> sessions) { + super(plugin, global, sessions); + } + + @Override + @NonNull protected Session createSession(final Player player) { + return new Session(player); + } + + /** + * Handles the slot-change packet-event sending the event if needed. + * + * @param player player for whom to handle slot change + * @param slot slot now selected by the player + * + * @implNote initializes the event object only if needed (event handler is not null) + */ + protected void handleSlotChanged(@NonNull final Player player, final int slot) { + val eventHandler = this.eventHandler.get(); + if (eventHandler != null) eventHandler.accept(new Event(player, (byte) (slot - 4))); + } + + /** + * Session of this scroll player controls + */ + public class Session extends AbstractPlayerControls.Session { + + public Session(final Player player) { + super(player); + } + } + + /** + * An event to be passed to event handler whenever a player scrolls. + */ + @Value + @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) + public static class Event { + + /** + * Player whose event this one is + */ + Player player; + + /** + * Positive value for scroll to right, negative value for scroll to left, {@code 0} for no update. + */ + byte delta; + } + + /** + * Function used to fill the player's hotbar with items. + */ + @FunctionalInterface + public interface HotbarFiller { + + /** + * Gets the item to be set in player's inventory at the specified slot. + * + * @param player player for whom to update the item in inventory + * @param slot value between {@code 0} and {@code 8} (inclusive), an index of hotbar slot (from left to right) + * @return non-empty optional containing a non-null item to be set in player's hotbar at the specified slot + * or empty optional if the slot should not be updated for the player + */ + Optional<@NonNull ItemStack> getItem(@Nonnull Player player, int slot); + } + + /** + * Packet handler to be used to intercept incoming selected-slot-change packets. + */ + protected class SlotChangePacketHandler extends PacketAdapter { + + public SlotChangePacketHandler() { + super(ScrollPlayerControls.this.plugin, PacketType.Play.Client.HELD_ITEM_SLOT); + } + + @Override + public void onPacketReceiving(final PacketEvent event) { + val player = event.getPlayer(); + if (sessions.containsKey(player)) { + handleSlotChanged(player, new WrapperPlayClientHeldItemSlot(event.getPacket()).getSlot()); + event.setCancelled(true); + } + } + } +} From 8654e4b4dd40894d8871279dcd974566e71ecec4 Mon Sep 17 00:00:00 2001 From: JarvisCraft Date: Thu, 31 Jan 2019 18:53:58 +0300 Subject: [PATCH 13/13] Fix access restrictions of AbstractPlayerControls.Session --- .../minecraft/commons/control/AbstractPlayerControls.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java index 89bc21f7c..ebcba0dc7 100644 --- a/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java +++ b/commons/src/main/java/ru/progrm_jarvis/minecraft/commons/control/AbstractPlayerControls.java @@ -122,7 +122,7 @@ public Consumer unsubscribe() { @EqualsAndHashCode @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) - protected abstract class Session implements PlayerControls.Session { + public abstract class Session implements PlayerControls.Session { /** * Player whose session this one is