-
-
Notifications
You must be signed in to change notification settings - Fork 25
GH-1301 Add paginated ender chests #1440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Pawelusze
wants to merge
8
commits into
EternalCodeTeam:master
Choose a base branch
from
Pawelusze:feature/paginated-enderchest
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+2,321
−62
Draft
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a35447f
Add paginated ender chests
Pawelusze 9d76c02
Replace the enderchest writer thread with the shared repository executor
Pawelusze 02954d9
Shorten enderchest config comments
Pawelusze 47dee62
rename command arg method
Pawelusze 663bced
Fix the ItemCodec comment to mention Paper instead of Bukkit
Pawelusze 933fae0
Move enderchest item serialization behind an ORMLite persister
Pawelusze 7250b97
Fix lost writes and premature item access during enderchest import
Pawelusze 5c359f8
Store only non-empty slots, like vanilla does
Pawelusze File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
eternalcore-api/src/main/java/com/eternalcode/core/feature/enderchest/EnderchestService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package com.eternalcode.core.feature.enderchest; | ||
|
|
||
| import org.bukkit.OfflinePlayer; | ||
| import org.bukkit.entity.Player; | ||
|
|
||
| /** | ||
| * Paginated ender chests. When the feature is disabled the vanilla ender chest is used and only | ||
| * {@link #openEnderchest(Player)} does anything; when ender chests are blocked nothing opens at all. | ||
| */ | ||
| public interface EnderchestService { | ||
|
|
||
| /** | ||
| * @return whether ender chests are blocked entirely, which overrides {@link #isVanillaEnderchestReplaced()} | ||
| */ | ||
| boolean areEnderchestsBlocked(); | ||
|
|
||
| /** | ||
| * @return whether paginated ender chests are enabled in the configuration | ||
| */ | ||
| boolean isVanillaEnderchestReplaced(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Co to oznacza? Jeśli to dotyczy konfiguracji i tego, czy enderchesty mają być paginated - to nazwa metody do zmiany |
||
|
|
||
| /** | ||
| * Opens the player's own ender chest: the first page when the feature is enabled, the vanilla | ||
| * ender chest otherwise. Does nothing while ender chests are blocked. | ||
| * | ||
| * @param player the player to open the chest for | ||
| */ | ||
| void openEnderchest(Player player); | ||
|
|
||
| /** | ||
| * Opens a page of the owner's ender chest to the viewer. The owner may be offline. The viewer is | ||
| * notified when the page is beyond the owner's reach. Does nothing when the feature is disabled or | ||
| * ender chests are blocked. | ||
| * | ||
| * @param viewer the player who sees and edits the page | ||
| * @param owner the player whose chest is opened, online or not | ||
| * @param page 1-based page number | ||
| */ | ||
| void openEnderchest(Player viewer, OfflinePlayer owner, int page); | ||
|
|
||
| /** | ||
| * @param player the player to evaluate | ||
| * @return number of pages the player's permissions grant, at least 1; pages that already hold items | ||
| * stay reachable beyond this limit | ||
| */ | ||
| int getPageLimit(Player player); | ||
| } | ||
58 changes: 58 additions & 0 deletions
58
...-api/src/main/java/com/eternalcode/core/feature/enderchest/event/EnderchestOpenEvent.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package com.eternalcode.core.feature.enderchest.event; | ||
|
|
||
| import java.util.UUID; | ||
| import org.bukkit.event.Cancellable; | ||
| import org.bukkit.event.Event; | ||
| import org.bukkit.event.HandlerList; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| /** | ||
| * Called right before a page of a paginated ender chest is shown to a viewer. | ||
| */ | ||
| public class EnderchestOpenEvent extends Event implements Cancellable { | ||
|
|
||
| private static final HandlerList HANDLER_LIST = new HandlerList(); | ||
|
|
||
| private final UUID viewerUniqueId; | ||
| private final UUID ownerUniqueId; | ||
| private final int page; | ||
| private boolean cancelled; | ||
|
|
||
| public EnderchestOpenEvent(UUID viewerUniqueId, UUID ownerUniqueId, int page) { | ||
| super(false); | ||
| this.viewerUniqueId = viewerUniqueId; | ||
| this.ownerUniqueId = ownerUniqueId; | ||
| this.page = page; | ||
| } | ||
|
|
||
| public UUID getViewerUniqueId() { | ||
| return this.viewerUniqueId; | ||
| } | ||
|
|
||
| public UUID getOwnerUniqueId() { | ||
| return this.ownerUniqueId; | ||
| } | ||
|
|
||
| public int getPage() { | ||
| return this.page; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isCancelled() { | ||
| return this.cancelled; | ||
| } | ||
|
|
||
| @Override | ||
| public void setCancelled(boolean cancelled) { | ||
| this.cancelled = cancelled; | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull HandlerList getHandlers() { | ||
| return HANDLER_LIST; | ||
| } | ||
|
|
||
| public static HandlerList getHandlerList() { | ||
| return HANDLER_LIST; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
...e-core/src/main/java/com/eternalcode/core/database/persister/ItemStackArrayPersister.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| package com.eternalcode.core.database.persister; | ||
|
|
||
| import com.j256.ormlite.field.FieldType; | ||
| import com.j256.ormlite.field.SqlType; | ||
| import com.j256.ormlite.field.types.BaseDataType; | ||
| import com.j256.ormlite.support.DatabaseResults; | ||
| import java.io.ByteArrayInputStream; | ||
| import java.io.ByteArrayOutputStream; | ||
| import java.io.DataInputStream; | ||
| import java.io.DataOutputStream; | ||
| import java.io.IOException; | ||
| import java.sql.SQLException; | ||
| import org.bukkit.inventory.ItemStack; | ||
|
|
||
| // Paper only added serializeItemsAsBytes in 1.21.1, so we encode item by item to stay usable on 1.19.3. | ||
| // The per item serializeAsBytes we call here differs by one word, easy to mix the two up. | ||
| public class ItemStackArrayPersister extends BaseDataType { | ||
|
|
||
| private static final ItemStackArrayPersister INSTANCE = new ItemStackArrayPersister(); | ||
|
|
||
| private static final byte FORMAT_VERSION = 3; | ||
| private static final int MAX_SLOTS = 1024; | ||
|
|
||
| private ItemStackArrayPersister() { | ||
| super(SqlType.BYTE_ARRAY, new Class<?>[] { ItemStack[].class }); | ||
| } | ||
|
|
||
| @Override | ||
| public Object javaToSqlArg(FieldType fieldType, Object javaObject) { | ||
| return encode((ItemStack[]) javaObject); | ||
| } | ||
|
|
||
| @Override | ||
| public Object resultToSqlArg(FieldType fieldType, DatabaseResults results, int columnPos) throws SQLException { | ||
| return results.getBytes(columnPos); | ||
| } | ||
|
|
||
| @Override | ||
| public Object sqlArgToJava(FieldType fieldType, Object sqlArg, int columnPos) { | ||
| return decode((byte[]) sqlArg); | ||
| } | ||
|
|
||
| @Override | ||
| public Object parseDefaultString(FieldType fieldType, String defaultStr) throws SQLException { | ||
| throw new SQLException("Items cannot be given a default value"); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isArgumentHolderRequired() { | ||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
| public Class<?> getPrimaryClass() { | ||
| return ItemStack[].class; | ||
| } | ||
|
|
||
| public static ItemStackArrayPersister getSingleton() { | ||
| return INSTANCE; | ||
| } | ||
|
|
||
| private static byte[] encode(ItemStack[] items) { | ||
| ByteArrayOutputStream buffer = new ByteArrayOutputStream(); | ||
|
|
||
| try (DataOutputStream output = new DataOutputStream(buffer)) { | ||
| output.writeByte(FORMAT_VERSION); | ||
| output.writeInt(items.length); | ||
| output.writeInt(countStored(items)); | ||
|
|
||
| for (int slot = 0; slot < items.length; slot++) { | ||
| ItemStack item = items[slot]; | ||
| if (item == null) { | ||
| continue; | ||
| } | ||
|
|
||
| byte[] serialized = item.serializeAsBytes(); | ||
| output.writeInt(slot); | ||
| output.writeInt(serialized.length); | ||
| output.write(serialized); | ||
| } | ||
| } | ||
| catch (IOException exception) { | ||
| throw new IllegalStateException("Failed to encode items", exception); | ||
| } | ||
|
|
||
| return buffer.toByteArray(); | ||
| } | ||
|
|
||
| private static int countStored(ItemStack[] items) { | ||
| int stored = 0; | ||
|
|
||
| for (ItemStack item : items) { | ||
| if (item != null) { | ||
| stored++; | ||
| } | ||
| } | ||
|
|
||
| return stored; | ||
| } | ||
|
|
||
| private static ItemStack[] decode(byte[] bytes) { | ||
| if (bytes == null) { | ||
| return new ItemStack[0]; | ||
| } | ||
|
|
||
| if (bytes.length == 0) { | ||
| throw new IllegalStateException("Stored items are empty, the row is corrupted"); | ||
| } | ||
|
|
||
| try (DataInputStream input = new DataInputStream(new ByteArrayInputStream(bytes))) { | ||
| byte version = input.readByte(); | ||
| if (version != FORMAT_VERSION) { | ||
| throw new IllegalStateException("Unknown item format: " + version); | ||
| } | ||
|
|
||
| int slots = input.readInt(); | ||
| if (slots < 0 || slots > MAX_SLOTS) { | ||
| throw new IllegalStateException("Item array declares " + slots + " slots"); | ||
| } | ||
|
|
||
| int stored = input.readInt(); | ||
| if (stored < 0 || stored > slots) { | ||
| throw new IllegalStateException("Item array declares " + stored + " items in " + slots + " slots"); | ||
| } | ||
|
|
||
| ItemStack[] items = new ItemStack[slots]; | ||
| for (int index = 0; index < stored; index++) { | ||
| int slot = input.readInt(); | ||
| if (slot < 0 || slot >= slots) { | ||
| throw new IllegalStateException("Item points at slot " + slot + " outside of " + slots); | ||
| } | ||
|
|
||
| int length = input.readInt(); | ||
| if (length <= 0 || length > bytes.length) { | ||
| throw new IllegalStateException("Slot " + slot + " declares " + length + " bytes"); | ||
| } | ||
|
|
||
| byte[] serialized = new byte[length]; | ||
| input.readFully(serialized); | ||
| items[slot] = ItemStack.deserializeBytes(serialized); | ||
| } | ||
|
|
||
| return items; | ||
| } | ||
| catch (IOException exception) { | ||
| throw new IllegalStateException("Failed to decode items", exception); | ||
| } | ||
| } | ||
| } |
53 changes: 0 additions & 53 deletions
53
eternalcore-core/src/main/java/com/eternalcode/core/feature/container/EnderchestCommand.java
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Co to oznacza? dajmy tutaj szczegółowsze javadocs'y lub lepszą nazwę tej metody