mirror of
https://github.com/Jikoo/OpenInv.git
synced 2026-11-04 08:42:05 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc239aa70b | ||
|
|
e27d996ad8 | ||
|
|
98230c6f5b | ||
|
|
53c9586220 | ||
|
|
15a8052115 | ||
|
|
fae3231272 | ||
|
|
3820d2e974 | ||
|
|
337ba2c35a | ||
|
|
fdf7f68c51 | ||
|
|
f1253fea6f | ||
|
|
5af49a6bbd | ||
|
|
e8c01c7893 | ||
|
|
1675952e94 | ||
|
|
35e39ffd3e | ||
|
|
7da27a0da0 | ||
|
|
180ceaf7e1 | ||
|
|
e608233ad9 | ||
|
|
d787516fce | ||
|
|
50c522b8f6 | ||
|
|
0192f5a6a9 | ||
|
|
8123679c46 | ||
|
|
1d37aad00a | ||
|
|
27a6e59682 | ||
|
|
f72e22c2a1 | ||
|
|
55053dacbf | ||
|
|
dacb07bd41 | ||
|
|
06d3fd7df9 | ||
|
|
4acf43b0fe | ||
|
|
a570001eaf | ||
|
|
70c53521c1 | ||
|
|
9021ef9a22 | ||
|
|
722ab4d2a3 | ||
|
|
5f04575780 | ||
|
|
0f5368b134 | ||
|
|
b43a32139d | ||
|
|
98d819c49a | ||
|
|
8f058fb206 | ||
|
|
60a32b7af5 | ||
|
|
61f7d5cee5 | ||
|
|
3d65681c6f | ||
|
|
cf2f53f9e9 | ||
|
|
95ae1cfa0a | ||
|
|
07451de7a3 | ||
|
|
872e14e1a6 | ||
|
|
f5e534f758 | ||
|
|
16a4c8f71b | ||
|
|
7f4216995c | ||
|
|
f945868a21 | ||
|
|
ee923c0881 | ||
|
|
80d48ed218 | ||
|
|
8de1f778f0 | ||
|
|
8955882737 | ||
|
|
037b3f89cd | ||
|
|
43b4360bb6 | ||
|
|
e03c43555d | ||
|
|
43a13e6254 | ||
|
|
ab3dddbc19 | ||
|
|
d35fc6713b | ||
|
|
9c8a16adc9 | ||
|
|
b93900cf3b | ||
|
|
63fccdcf91 | ||
|
|
960acbfe9d | ||
|
|
3c904499c5 | ||
|
|
baa6b3d734 | ||
|
|
7f6c339e06 | ||
|
|
00736c8d30 | ||
|
|
cb1ec77c24 | ||
|
|
c8c8a72819 | ||
|
|
16f91ddc9f | ||
|
|
c83511e475 | ||
|
|
c095a78013 | ||
|
|
4441cdcf04 | ||
|
|
9940b9d840 | ||
|
|
fb409f8024 | ||
|
|
08b43a8aca | ||
|
|
3df3d41a7f | ||
|
|
16cba8a137 | ||
|
|
f1b86b4eb1 | ||
|
|
172e1cd55b | ||
|
|
d8b5aa145b | ||
|
|
2ffff99acf | ||
|
|
743c46f322 | ||
|
|
e3285a6d61 | ||
|
|
806fb848a7 | ||
|
|
b269a5ed3c | ||
|
|
8c102c4400 | ||
|
|
080d02f93f | ||
|
|
54f9d30a89 | ||
|
|
6063959362 | ||
|
|
d80b8a6f4d | ||
|
|
13621901ad | ||
|
|
20cc6e004e | ||
|
|
80585dfc07 | ||
|
|
9e37b42c63 | ||
|
|
58be5cffc9 | ||
|
|
e8c8e625c0 | ||
|
|
0ee3f8c1b2 | ||
|
|
99f9099981 | ||
|
|
70ae432158 | ||
|
|
ad05f427fd | ||
|
|
252e93f872 | ||
|
|
0267090cb6 |
No files matched your search
@@ -8,3 +8,12 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
ignore:
|
||||
# The SQLite JDBC is provided by Spigot and, for now, Paper.
|
||||
# To ensure it is still present even if Paper stops providing it,
|
||||
# we need to declare it as a library.
|
||||
# To prevent needlessly downloading (and loading) a second copy,
|
||||
# we want to ensure that we are using the provided version.
|
||||
- dependency-name: "org.xerial:sqlite-jdbc"
|
||||
# Spigot and Spigot API updates are manual.
|
||||
- dependency-name: "org.spigotmc:*"
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
# Note: this is directly from GitHub's example for using data from a triggering workflow:
|
||||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow
|
||||
- name: 'Download artifact'
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
|
||||
@@ -15,33 +15,22 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
- uses: actions/setup-java@v6
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
java-version: '25'
|
||||
|
||||
# We can't use 'maven' prebuilt cache setup because it requires that the project have a pom file.
|
||||
# BuildTools installs to Maven local if available, so it's easier to just rely on that.
|
||||
- name: Cache Spigot dependency
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.m2/repository/org/spigotmc/
|
||||
key: ${{ runner.os }}-buildtools-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildtools-
|
||||
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
- uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew clean build
|
||||
run: ./gradlew build
|
||||
|
||||
# Upload artifacts
|
||||
- name: Upload Distributable Jar
|
||||
id: upload-final
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: dist
|
||||
path: ./dist/*
|
||||
@@ -13,24 +13,26 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
|
||||
- name: Create Release
|
||||
id: create-release
|
||||
uses: softprops/action-gh-release@v2.3.2
|
||||
uses: softprops/action-gh-release@v3.0.3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: OpenInv ${{ env.VERSIONED_NAME }}
|
||||
name: "OpenInv ${{ github.ref_name }}"
|
||||
body: |-
|
||||
## Supported server versions
|
||||
**Paper:** TODO VERSION, 1.21.4, 1.21.3, 1.21.1
|
||||
|
||||
**Paper:** TODO VERSION, 26.1.2, 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6
|
||||
**Spigot:** TODO VERSION
|
||||
|
||||
TODO HELLO HUMAN, PRESS THE GENERATE CHANGELOG BUTTON PLEASE.
|
||||
Don't forget to add a newline after the resulting header and prettify the tag compare link!
|
||||
draft: true
|
||||
prerelease: false
|
||||
files: ./dist/**
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Release to CurseForge
|
||||
name: Release to external sites
|
||||
|
||||
on:
|
||||
release:
|
||||
@@ -8,30 +8,103 @@ jobs:
|
||||
curseforge_release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- &parse-paper-versions
|
||||
name: Parse Paper Versions
|
||||
id: parse_versions
|
||||
run: |
|
||||
# Find line declaring Paper versions.
|
||||
raw=$(grep "\\*\\*Paper:\\*\\*" <<< "${{ github.event.release.body }}")
|
||||
|
||||
- name: Fetch Github Release Asset
|
||||
# Enable extended glob pattern to match 0 or more whitespace characters.
|
||||
shopt -s extglob
|
||||
# Trim Paper versions identifier prefix.
|
||||
raw=${raw/*([[:space:]])'**'Paper:'**'*([[:space:]])/}
|
||||
# Replace commas and optional spaces with a newline.
|
||||
raw=${raw//,*([[:space:]])/$'\n'}
|
||||
# Turn extglob back off.
|
||||
shopt -u extglob
|
||||
|
||||
echo "$raw"
|
||||
printf "PAPER_VERSIONS<<EOF\n%s\nEOF\n" "$raw" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- &fetch-release-asset
|
||||
name: Fetch Github Release Asset
|
||||
uses: dsaltares/fetch-gh-release-asset@1.1.2
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
version: ${{ github.event.release.id }}
|
||||
file: OpenInv.jar
|
||||
|
||||
- name: Set CurseForge Variables
|
||||
run: . scripts/set_curseforge_env.sh "${{ github.event.release.body }}"
|
||||
|
||||
- name: Create CurseForge Release
|
||||
uses: itsmeow/curseforge-upload@v3
|
||||
uses: Kira-NT/mc-publish@v3.3
|
||||
with:
|
||||
token: "${{ secrets.CURSEFORGE_TOKEN }}"
|
||||
project_id: 31432
|
||||
game_endpoint: minecraft
|
||||
file_path: ./OpenInv.jar
|
||||
display_name: "${{ github.event.release.name }}"
|
||||
game_versions: "${{ env.CURSEFORGE_MINECRAFT_VERSIONS }}"
|
||||
release_type: release
|
||||
changelog_type: markdown
|
||||
changelog: "${{ github.event.release.body }}"
|
||||
curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }}
|
||||
curseforge-id: 31432
|
||||
files: ./OpenInv.jar
|
||||
game-versions: "${{ steps.parse_versions.outputs.PAPER_VERSIONS }}"
|
||||
game-version-filter: releases
|
||||
loaders: |
|
||||
spigot
|
||||
paper
|
||||
folia
|
||||
|
||||
modrinth_release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- *parse-paper-versions
|
||||
- *fetch-release-asset
|
||||
|
||||
- name: Create Modrinth Release
|
||||
uses: Kira-NT/mc-publish@v3.3
|
||||
with:
|
||||
modrinth-id: 1UlvXbzL
|
||||
modrinth-featured: false
|
||||
modrinth-unfeature-mode: none
|
||||
modrinth-token: ${{ secrets.MODRINTH_TOKEN }}
|
||||
files: ./OpenInv.jar
|
||||
game-versions: "${{ steps.parse_versions.outputs.PAPER_VERSIONS }}"
|
||||
game-version-filter: releases
|
||||
loaders: |
|
||||
spigot
|
||||
paper
|
||||
folia
|
||||
|
||||
hangar_release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Parse Hangar Paper Versions
|
||||
id: parse_versions
|
||||
run: |
|
||||
# Find line declaring Paper versions.
|
||||
raw=$(grep "\\*\\*Paper:\\*\\*" <<< "${{ github.event.release.body }}")
|
||||
# Trim Paper versions identifier prefix.
|
||||
raw="${raw/'**'Paper:'**'/}"
|
||||
# Trim leading and trailing spaces.
|
||||
raw="${raw##[[:space:]]}"
|
||||
raw="${raw%%[[:space:]]}"
|
||||
|
||||
# Generate JSON for Hangar. GitHub Actions provides jq 1.7 in the 24.04 image.
|
||||
# Split on comma and optional spaces.
|
||||
hangar_versions=$(jq -nc --arg versions "$raw" '{"PAPER": $versions | split(", *";null)}')
|
||||
|
||||
echo "$hangar_versions"
|
||||
echo "HANGAR_PAPER_VERSIONS=$hangar_versions" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- *fetch-release-asset
|
||||
|
||||
- name: Create Hangar Release
|
||||
uses: benwoo1110/hangar-upload-action@v1
|
||||
with:
|
||||
api_token: ${{ secrets.HANGAR_TOKEN }}
|
||||
slug: 'OpenInv'
|
||||
version: ${{ github.event.release.tag_name }}
|
||||
channel: release
|
||||
description: "${{ github.event.release.body }}"
|
||||
files: |-
|
||||
[
|
||||
{
|
||||
"path": "./OpenInv.jar",
|
||||
"platforms": ["PAPER"]
|
||||
}
|
||||
]
|
||||
platform_dependencies: "${{ steps.parse_versions.outputs.HANGAR_PAPER_VERSIONS }}"
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p ./pr
|
||||
echo ${{ github.event.number }} > ./pr/pr_number
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: pr_number
|
||||
path: pr/
|
||||
@@ -13,11 +13,11 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Build resource pack
|
||||
id: upload-resource-pack
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: openinv-legibility-pack
|
||||
path: ./resource-pack/openinv-legibility-pack/
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
**/dist/
|
||||
**/dependency-reduced-pom.xml
|
||||
**/pom.xml.versionsBackup
|
||||
**/.vscode/
|
||||
@@ -1,8 +1,10 @@
|
||||
## About
|
||||
|
||||
OpenInv is a [Bukkit plugin](https://dev.bukkit.org/projects/openinv) which allows users to open and edit anyone's
|
||||
OpenInv is a Bukkit plugin which allows users to open and edit anyone's
|
||||
inventory or ender chest - online or not!
|
||||
|
||||
Downloads are available on [GitHub](https://github.com/Jikoo/OpenInv/releases), [DBO](https://dev.bukkit.org/projects/openinv)/[CurseForge](https://www.curseforge.com/minecraft/bukkit-plugins/openinv), [Modrinth](https://modrinth.com/plugin/openinv), and [Hangar](https://hangar.papermc.io/jikoo/OpenInv).
|
||||
|
||||
## Features
|
||||
|
||||
- **OpenInv**: Open anyone's inventory, even if they're offline.
|
||||
@@ -17,6 +19,7 @@ inventory or ender chest - online or not!
|
||||
- Cross-world support! Allow access only from the same world.
|
||||
- **SilentContainer**: Open containers without displaying an animation or making sound.
|
||||
- **AnyContainer**: Open containers, even if blocked by ocelots or blocks.
|
||||
- **Resource Pack Support**: Personalize view using resource pack tricks like custom fonts and characters. See [the wiki](https://github.com/Jikoo/OpenInv/wiki/Customizing-Inventories) for details.
|
||||
|
||||
## Commands
|
||||
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.spigotapi)
|
||||
implementation(project(":openinvapi"))
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.release = 21
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
expand("version" to version)
|
||||
}
|
||||
|
||||
+17
-1
@@ -1,8 +1,24 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.spigotapi)
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.release = 21
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("jitpack") {
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
@@ -33,6 +33,7 @@ import java.util.logging.Logger;
|
||||
/**
|
||||
* Interface defining behavior for the OpenInv plugin.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface IOpenInv {
|
||||
|
||||
/**
|
||||
@@ -76,7 +77,7 @@ public interface IOpenInv {
|
||||
* @return the active implementation for the server version
|
||||
* @throws IllegalStateException if the server version is unsupported
|
||||
*/
|
||||
@NotNull IAnySilentContainer getAnySilentContainer();
|
||||
IAnySilentContainer getAnySilentContainer();
|
||||
|
||||
/**
|
||||
* Get whether a user has AnyContainer mode enabled.
|
||||
@@ -84,7 +85,7 @@ public interface IOpenInv {
|
||||
* @param offline the user to obtain the state of
|
||||
* @return true if AnyContainer mode is enabled
|
||||
*/
|
||||
boolean getAnyContainerStatus(@NotNull OfflinePlayer offline);
|
||||
boolean getAnyContainerStatus(OfflinePlayer offline);
|
||||
|
||||
/**
|
||||
* Set whether a user has AnyContainer mode enabled.
|
||||
@@ -92,7 +93,7 @@ public interface IOpenInv {
|
||||
* @param offline the user to set the state of
|
||||
* @param status the state of the mode
|
||||
*/
|
||||
void setAnyContainerStatus(@NotNull OfflinePlayer offline, boolean status);
|
||||
void setAnyContainerStatus(OfflinePlayer offline, boolean status);
|
||||
|
||||
/**
|
||||
* Get whether a user has SilentContainer mode enabled.
|
||||
@@ -100,7 +101,7 @@ public interface IOpenInv {
|
||||
* @param offline the user to obtain the state of
|
||||
* @return true if SilentContainer mode is enabled
|
||||
*/
|
||||
boolean getSilentContainerStatus(@NotNull OfflinePlayer offline);
|
||||
boolean getSilentContainerStatus(OfflinePlayer offline);
|
||||
|
||||
/**
|
||||
* Set whether a user has SilentContainer mode enabled.
|
||||
@@ -108,7 +109,7 @@ public interface IOpenInv {
|
||||
* @param offline the user to set the state of
|
||||
* @param status the state of the mode
|
||||
*/
|
||||
void setSilentContainerStatus(@NotNull OfflinePlayer offline, boolean status);
|
||||
void setSilentContainerStatus(OfflinePlayer offline, boolean status);
|
||||
|
||||
/**
|
||||
* Get an {@link ISpecialEnderChest} for a user.
|
||||
@@ -119,8 +120,8 @@ public interface IOpenInv {
|
||||
* @throws IllegalStateException if the server version is unsupported
|
||||
* @throws InstantiationException if there was an issue creating the inventory
|
||||
*/
|
||||
@NotNull ISpecialEnderChest getSpecialEnderChest(
|
||||
@NotNull Player player,
|
||||
ISpecialEnderChest getSpecialEnderChest(
|
||||
Player player,
|
||||
boolean online
|
||||
) throws InstantiationException;
|
||||
|
||||
@@ -133,19 +134,26 @@ public interface IOpenInv {
|
||||
* @throws IllegalStateException if the server version is unsupported
|
||||
* @throws InstantiationException if there was an issue creating the inventory
|
||||
*/
|
||||
@NotNull ISpecialPlayerInventory getSpecialInventory(
|
||||
@NotNull Player player,
|
||||
ISpecialPlayerInventory getSpecialInventory(
|
||||
Player player,
|
||||
boolean online
|
||||
) throws InstantiationException;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #openInventory(Player, ISpecialInventory, boolean)}
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "5.2.0")
|
||||
@Nullable InventoryView openInventory(Player player, ISpecialInventory inventory);
|
||||
|
||||
/**
|
||||
* Open an {@link ISpecialInventory} for a {@link Player}.
|
||||
*
|
||||
* @param player the viewer
|
||||
* @param inventory the inventory to open
|
||||
* @param viewOnly whether the inventory should be view-only
|
||||
* @return the resulting {@link InventoryView}
|
||||
*/
|
||||
@Nullable InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory);
|
||||
@Nullable InventoryView openInventory(Player player, ISpecialInventory inventory, boolean viewOnly);
|
||||
|
||||
/**
|
||||
* Check if a {@link Player} is currently loaded by OpenInv.
|
||||
@@ -154,7 +162,7 @@ public interface IOpenInv {
|
||||
* @return whether the {@code Player} is loaded
|
||||
* @since 4.2.0
|
||||
*/
|
||||
boolean isPlayerLoaded(@NotNull UUID playerUuid);
|
||||
boolean isPlayerLoaded(UUID playerUuid);
|
||||
|
||||
/**
|
||||
* Load a {@link Player} from an {@link OfflinePlayer}. If the user has not played before or the default world for
|
||||
@@ -164,7 +172,7 @@ public interface IOpenInv {
|
||||
* @return the loaded {@code Player}
|
||||
* @throws IllegalStateException if the server version is unsupported
|
||||
*/
|
||||
@Nullable Player loadPlayer(@NotNull final OfflinePlayer offline);
|
||||
@Nullable Player loadPlayer(final OfflinePlayer offline);
|
||||
|
||||
/**
|
||||
* Match an existing {@link OfflinePlayer}. If the name is a {@link UUID#toString() UUID string}, this will only
|
||||
@@ -177,14 +185,14 @@ public interface IOpenInv {
|
||||
* @param name the string to match
|
||||
* @return the user with the closest matching name
|
||||
*/
|
||||
@Nullable OfflinePlayer matchPlayer(@NotNull String name);
|
||||
@Nullable OfflinePlayer matchPlayer(String name);
|
||||
|
||||
/**
|
||||
* Forcibly close inventories of and unload any cached data for a user.
|
||||
*
|
||||
* @param offline the {@link OfflinePlayer} to unload
|
||||
*/
|
||||
void unload(@NotNull OfflinePlayer offline);
|
||||
void unload(OfflinePlayer offline);
|
||||
|
||||
Logger getLogger();
|
||||
|
||||
|
||||
@@ -5,11 +5,12 @@ import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Event fired before OpenInv saves a player's data when closing an {@link ISpecialInventory}.
|
||||
*/
|
||||
@NullMarked
|
||||
public class OpenPlayerSaveEvent extends PlayerSaveEvent {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
@@ -26,10 +27,11 @@ public class OpenPlayerSaveEvent extends PlayerSaveEvent {
|
||||
*/
|
||||
@RestrictedApi(
|
||||
explanation = "Constructor is not considered part of the API and may be subject to change.",
|
||||
link = "",
|
||||
allowedOnPath = ".*/com/lishid/openinv/event/OpenEvents.java"
|
||||
)
|
||||
@ApiStatus.Internal
|
||||
OpenPlayerSaveEvent(@NotNull Player player, @NotNull ISpecialInventory inventory) {
|
||||
OpenPlayerSaveEvent(Player player, ISpecialInventory inventory) {
|
||||
super(player);
|
||||
this.inventory = inventory;
|
||||
}
|
||||
@@ -39,11 +41,10 @@ public class OpenPlayerSaveEvent extends PlayerSaveEvent {
|
||||
*
|
||||
* @return the special inventory
|
||||
*/
|
||||
public @NotNull ISpecialInventory getInventory() {
|
||||
public ISpecialInventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
|
||||
@@ -7,11 +7,12 @@ import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Event fired before a {@link Player} loaded via OpenInv is saved.
|
||||
*/
|
||||
@NullMarked
|
||||
public class PlayerSaveEvent extends PlayerEvent implements Cancellable {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
@@ -27,10 +28,11 @@ public class PlayerSaveEvent extends PlayerEvent implements Cancellable {
|
||||
*/
|
||||
@RestrictedApi(
|
||||
explanation = "Constructor is not considered part of the API and may be subject to change.",
|
||||
link = "",
|
||||
allowedOnPath = ".*/com/lishid/openinv/event/(OpenPlayerSaveEvent|OpenEvents).java"
|
||||
)
|
||||
@ApiStatus.Internal
|
||||
PlayerSaveEvent(@NotNull Player player) {
|
||||
PlayerSaveEvent(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@@ -54,7 +56,6 @@ public class PlayerSaveEvent extends PlayerEvent implements Cancellable {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
|
||||
@@ -5,27 +5,29 @@ import com.lishid.openinv.util.setting.PlayerToggle;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Event fired after OpenInv modifies a toggleable setting for a player.
|
||||
*/
|
||||
@NullMarked
|
||||
public class PlayerToggledEvent extends Event {
|
||||
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final @NotNull PlayerToggle toggle;
|
||||
private final @NotNull UUID uuid;
|
||||
private final PlayerToggle toggle;
|
||||
private final UUID uuid;
|
||||
private final boolean enabled;
|
||||
|
||||
@RestrictedApi(
|
||||
explanation = "Constructor is not considered part of the API and may be subject to change.",
|
||||
link = "",
|
||||
allowedOnPath = ".*/com/lishid/openinv/event/OpenEvents.java"
|
||||
)
|
||||
@ApiStatus.Internal
|
||||
PlayerToggledEvent(@NotNull PlayerToggle toggle, @NotNull UUID uuid, boolean enabled) {
|
||||
PlayerToggledEvent(PlayerToggle toggle, UUID uuid, boolean enabled) {
|
||||
this.toggle = toggle;
|
||||
this.uuid = uuid;
|
||||
this.enabled = enabled;
|
||||
@@ -36,7 +38,7 @@ public class PlayerToggledEvent extends Event {
|
||||
*
|
||||
* @return the toggle
|
||||
*/
|
||||
public @NotNull PlayerToggle getToggle() {
|
||||
public PlayerToggle getToggle() {
|
||||
return toggle;
|
||||
}
|
||||
|
||||
@@ -45,7 +47,7 @@ public class PlayerToggledEvent extends Event {
|
||||
*
|
||||
* @return the player ID
|
||||
*/
|
||||
public @NotNull UUID getPlayerId() {
|
||||
public UUID getPlayerId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@@ -58,7 +60,6 @@ public class PlayerToggledEvent extends Event {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
|
||||
@@ -23,10 +23,13 @@ import org.bukkit.block.EnderChest;
|
||||
import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.entity.Cat;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public interface IAnySilentContainer {
|
||||
|
||||
/**
|
||||
@@ -38,14 +41,14 @@ public interface IAnySilentContainer {
|
||||
* @param block the {@link Block} of the container
|
||||
* @return true if the container can be opened
|
||||
*/
|
||||
boolean activateContainer(@NotNull Player player, boolean silent, @NotNull Block block);
|
||||
boolean activateContainer(Player player, boolean silent, Block block);
|
||||
|
||||
/**
|
||||
* Perform operations required to close the current container silently.
|
||||
*
|
||||
* @param player the {@link Player} closing a container
|
||||
*/
|
||||
void deactivateContainer(@NotNull Player player);
|
||||
void deactivateContainer(Player player);
|
||||
|
||||
/**
|
||||
* Check if the container at the given coordinates is blocked.
|
||||
@@ -53,7 +56,7 @@ public interface IAnySilentContainer {
|
||||
* @param block the {@link Block} of the container
|
||||
* @return true if the container is blocked
|
||||
*/
|
||||
boolean isAnyContainerNeeded(@NotNull Block block);
|
||||
boolean isAnyContainerNeeded(Block block);
|
||||
|
||||
/**
|
||||
* Check if a shulker box block cannot be opened under ordinary circumstances.
|
||||
@@ -61,7 +64,7 @@ public interface IAnySilentContainer {
|
||||
* @param shulkerBox the shulker box block
|
||||
* @return whether the container is blocked
|
||||
*/
|
||||
default boolean isShulkerBlocked(@NotNull Block shulkerBox) {
|
||||
default boolean isShulkerBlocked(Block shulkerBox) {
|
||||
Directional directional = (Directional) shulkerBox.getBlockData();
|
||||
BlockFace facing = directional.getFacing();
|
||||
// Construct a new 1-block bounding box at the origin.
|
||||
@@ -80,7 +83,7 @@ public interface IAnySilentContainer {
|
||||
* @param chest the chest block
|
||||
* @return whether the container is blocked
|
||||
*/
|
||||
default boolean isChestBlocked(@NotNull Block chest) {
|
||||
default boolean isChestBlocked(Block chest) {
|
||||
org.bukkit.block.Block relative = chest.getRelative(0, 1, 0);
|
||||
return relative.getType().isOccluding()
|
||||
|| !chest.getWorld().getNearbyEntities(BoundingBox.of(relative), Cat.class::isInstance).isEmpty();
|
||||
@@ -92,7 +95,7 @@ public interface IAnySilentContainer {
|
||||
* @param block the potential container
|
||||
* @return true if the type is a supported container
|
||||
*/
|
||||
boolean isAnySilentContainer(@NotNull Block block);
|
||||
boolean isAnySilentContainer(Block block);
|
||||
|
||||
/**
|
||||
* Check if the given {@link BlockState} is a container which can be unblocked or silenced.
|
||||
@@ -100,7 +103,7 @@ public interface IAnySilentContainer {
|
||||
* @param blockState the potential container
|
||||
* @return true if the type is a supported container
|
||||
*/
|
||||
default boolean isAnySilentContainer(@NotNull BlockState blockState) {
|
||||
default boolean isAnySilentContainer(BlockState blockState) {
|
||||
return (blockState instanceof InventoryHolder holder && isAnySilentContainer(holder))
|
||||
|| blockState instanceof EnderChest;
|
||||
}
|
||||
@@ -111,7 +114,7 @@ public interface IAnySilentContainer {
|
||||
* @param holder the potential container
|
||||
* @return true if the type is a supported container
|
||||
*/
|
||||
default boolean isAnySilentContainer(@NotNull InventoryHolder holder) {
|
||||
default boolean isAnySilentContainer(@Nullable InventoryHolder holder) {
|
||||
return holder instanceof org.bukkit.block.EnderChest
|
||||
|| holder instanceof org.bukkit.block.Chest
|
||||
|| holder instanceof org.bukkit.block.DoubleChest
|
||||
@@ -119,4 +122,12 @@ public interface IAnySilentContainer {
|
||||
|| holder instanceof org.bukkit.block.Barrel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given {@link Inventory} belongs to a container which can be unblocked or silenced.
|
||||
*
|
||||
* @param inventory the potential container inventory
|
||||
* @return true if the type is a supported container
|
||||
*/
|
||||
boolean isAnySilentContainer(Inventory inventory);
|
||||
|
||||
}
|
||||
@@ -17,15 +17,16 @@
|
||||
package com.lishid.openinv.internal;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* An {@link ISpecialInventory} representing an ender chest.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface ISpecialEnderChest extends ISpecialInventory {
|
||||
|
||||
@Override
|
||||
default @NotNull InventoryType getBukkitType() {
|
||||
default InventoryType getBukkitType() {
|
||||
return InventoryType.ENDER_CHEST;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,12 @@ import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* Interface defining behavior for special inventories backed by other inventories' content listings.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface ISpecialInventory {
|
||||
|
||||
/**
|
||||
@@ -32,21 +33,21 @@ public interface ISpecialInventory {
|
||||
*
|
||||
* @return the Bukkit inventory
|
||||
*/
|
||||
@NotNull Inventory getBukkitInventory();
|
||||
Inventory getBukkitInventory();
|
||||
|
||||
/**
|
||||
* Get the {@link InventoryType} corresponding to this {@code ISpecialInventory}.
|
||||
*
|
||||
* @return the type of Bukkit inventory
|
||||
*/
|
||||
@NotNull InventoryType getBukkitType();
|
||||
InventoryType getBukkitType();
|
||||
|
||||
/**
|
||||
* Set the owning {@link Player} instance to a newly-joined user.
|
||||
*
|
||||
* @param player the user coming online
|
||||
*/
|
||||
void setPlayerOnline(@NotNull Player player);
|
||||
void setPlayerOnline(Player player);
|
||||
|
||||
/**
|
||||
* Mark the owner of the inventory offline.
|
||||
@@ -70,6 +71,6 @@ public interface ISpecialInventory {
|
||||
*
|
||||
* @return the {@link HumanEntity} who owns the inventory
|
||||
*/
|
||||
@NotNull HumanEntity getPlayer();
|
||||
HumanEntity getPlayer();
|
||||
|
||||
}
|
||||
@@ -17,15 +17,16 @@
|
||||
package com.lishid.openinv.internal;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* An {@link ISpecialInventory} representing a player inventory.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface ISpecialPlayerInventory extends ISpecialInventory {
|
||||
|
||||
@Override
|
||||
default @NotNull InventoryType getBukkitType() {
|
||||
default InventoryType getBukkitType() {
|
||||
return InventoryType.PLAYER;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,15 @@ import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@NullMarked
|
||||
public final class InventoryAccess {
|
||||
|
||||
private static @Nullable BiFunction<Inventory, Class<? extends ISpecialInventory>, ISpecialInventory> provider;
|
||||
private static @Nullable BiFunction<Inventory, Class<? extends ISpecialInventory>, @Nullable ISpecialInventory> provider;
|
||||
|
||||
public static boolean isUsable() {
|
||||
return provider != null;
|
||||
@@ -41,7 +42,7 @@ public final class InventoryAccess {
|
||||
* @param inventory the Bukkit inventory
|
||||
* @return true if backed by the correct implementation
|
||||
*/
|
||||
public static boolean isPlayerInventory(@NotNull Inventory inventory) {
|
||||
public static boolean isPlayerInventory(Inventory inventory) {
|
||||
return getPlayerInventory(inventory) != null;
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ public final class InventoryAccess {
|
||||
* @param inventory the Bukkit inventory
|
||||
* @return the backing implementation if available
|
||||
*/
|
||||
public static @Nullable ISpecialPlayerInventory getPlayerInventory(@NotNull Inventory inventory) {
|
||||
public static @Nullable ISpecialPlayerInventory getPlayerInventory(Inventory inventory) {
|
||||
return provider == null ? null : (ISpecialPlayerInventory) provider.apply(inventory, ISpecialPlayerInventory.class);
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ public final class InventoryAccess {
|
||||
* @param inventory the Bukkit inventory
|
||||
* @return true if backed by the correct implementation
|
||||
*/
|
||||
public static boolean isEnderChest(@NotNull Inventory inventory) {
|
||||
public static boolean isEnderChest(Inventory inventory) {
|
||||
return getEnderChest(inventory) != null;
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@ public final class InventoryAccess {
|
||||
* @param inventory the Bukkit inventory
|
||||
* @return the backing implementation if available
|
||||
*/
|
||||
public static @Nullable ISpecialEnderChest getEnderChest(@NotNull Inventory inventory) {
|
||||
public static @Nullable ISpecialEnderChest getEnderChest(Inventory inventory) {
|
||||
return provider == null ? null : (ISpecialEnderChest) provider.apply(inventory, ISpecialEnderChest.class);
|
||||
}
|
||||
|
||||
@@ -84,17 +85,18 @@ public final class InventoryAccess {
|
||||
* @param inventory the Bukkit inventory
|
||||
* @return the backing implementation if available
|
||||
*/
|
||||
public static @Nullable ISpecialInventory getInventory(@NotNull Inventory inventory) {
|
||||
public static @Nullable ISpecialInventory getInventory(Inventory inventory) {
|
||||
return provider == null ? null : provider.apply(inventory, ISpecialInventory.class);
|
||||
}
|
||||
|
||||
@RestrictedApi(
|
||||
explanation = "Not part of the API.",
|
||||
link = "",
|
||||
allowedOnPath = ".*/com/lishid/openinv/util/InternalAccessor.java"
|
||||
)
|
||||
@ApiStatus.Internal
|
||||
static void setProvider(
|
||||
@Nullable BiFunction<Inventory, Class<? extends ISpecialInventory>, ISpecialInventory> provider
|
||||
@Nullable BiFunction<Inventory, Class<? extends ISpecialInventory>, @Nullable ISpecialInventory> provider
|
||||
) {
|
||||
InventoryAccess.provider = provider;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2022 lishid. All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.util;
|
||||
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* An enum containing all permissions directly checked by OpenInv.
|
||||
*
|
||||
* <p>Note that this is not an exhaustive list! This does not contain
|
||||
* all permissions managed by Bukkit, largely parent nodes.</p>
|
||||
*/
|
||||
@NullMarked
|
||||
public enum Permissions {
|
||||
|
||||
/// Permission to open one's own inventory.
|
||||
INVENTORY_OPEN_SELF("inventory.open.self"),
|
||||
/// Permission to open someone else's inventory.
|
||||
INVENTORY_OPEN_OTHER("inventory.open.other"),
|
||||
/**
|
||||
* Permission to edit one's own inventory.
|
||||
*
|
||||
* <p>Note that this does not guarantee that the user has access to open the inventory!
|
||||
* Be sure to check {@link #INVENTORY_OPEN_SELF} first.</p>
|
||||
*/
|
||||
INVENTORY_EDIT_SELF("inventory.edit.self"),
|
||||
/**
|
||||
* Permission to edit someone else's inventory.
|
||||
*
|
||||
* <p>Note that this does not guarantee that the user has access to open the inventory!
|
||||
* Be sure to check {@link #INVENTORY_OPEN_OTHER} first.</p>
|
||||
*/
|
||||
INVENTORY_EDIT_OTHER("inventory.edit.other"),
|
||||
/// Permission to insert any item into the head slot.
|
||||
INVENTORY_SLOT_HEAD_ANY("inventory.slot.head.any"),
|
||||
/// Permission to insert any item into the chest slot.
|
||||
INVENTORY_SLOT_CHEST_ANY("inventory.slot.chest.any"),
|
||||
/// Permission to insert any item into the legs slot.
|
||||
INVENTORY_SLOT_LEGS_ANY("inventory.slot.legs.any"),
|
||||
/// Permission to insert any item into the feet slot.
|
||||
INVENTORY_SLOT_FEET_ANY("inventory.slot.feet.any"),
|
||||
/// Permission to drop items as the player via the drop slot.
|
||||
INVENTORY_SLOT_DROP("inventory.slot.drop"),
|
||||
|
||||
/// Permission to open one's own ender chest.
|
||||
ENDERCHEST_OPEN_SELF("enderchest.open.self"),
|
||||
/// Permission to open someone else's ender chest.
|
||||
ENDERCHEST_OPEN_OTHER("enderchest.open.other"),
|
||||
/**
|
||||
* Permission to edit one's own ender chest.
|
||||
*
|
||||
* <p>Note that this does not guarantee that the user has access to open the inventory!
|
||||
* Be sure to check {@link #ENDERCHEST_OPEN_SELF} first.</p>
|
||||
*/
|
||||
ENDERCHEST_EDIT_SELF("enderchest.edit.self"),
|
||||
/**
|
||||
* Permission to edit someone else's ender chest.
|
||||
*
|
||||
* <p>Note that this does not guarantee that the user has access to open the inventory!
|
||||
* Be sure to check {@link #ENDERCHEST_OPEN_OTHER} first.</p>
|
||||
*/
|
||||
ENDERCHEST_EDIT_OTHER("enderchest.edit.other"),
|
||||
|
||||
/// Permission to clear one's own inventory.
|
||||
CLEAR_SELF("clear.self"),
|
||||
/// Permission to clear someone else's inventory.
|
||||
CLEAR_OTHER("clear.other"),
|
||||
|
||||
/// Permission to view inventories and ender chests from other worlds.
|
||||
ACCESS_CROSSWORLD("access.crossworld"),
|
||||
/// Permission to access offline players' inventories and ender chests.
|
||||
ACCESS_OFFLINE("access.offline"),
|
||||
/// Permission to access online players' inventories and ender chests.
|
||||
ACCESS_ONLINE("access.online"),
|
||||
/// Permission granting the ability to edit players with the same access level.
|
||||
ACCESS_EQUAL_EDIT("access.equal.edit"),
|
||||
/// Permission to view, but not edit, players with the same access level.
|
||||
ACCESS_EQUAL_VIEW("access.equal.view"),
|
||||
/// Permission to deny access to players with the same access level.
|
||||
ACCESS_EQUAL_DENY("access.equal.deny"),
|
||||
|
||||
/// Permission to perform inventory interaction while in spectator mode.
|
||||
SPECTATE_CLICK("spectate.click"),
|
||||
|
||||
/// Permission to use the AnyContainer feature.
|
||||
CONTAINER_ANY("container.any"),
|
||||
/// Permission to use the AnyContainer feature but not the command to toggle it.
|
||||
CONTAINER_ANY_USE("container.any.use"),
|
||||
/// Permission to use the SilentContainer feature.
|
||||
CONTAINER_SILENT("container.silent"),
|
||||
/// Permission to use the SilentContainer feature but not the command to toggle it.
|
||||
CONTAINER_SILENT_USE("container.silent.use"),
|
||||
/// Permission to search inventories and ender chests.
|
||||
SEARCH_INVENTORY("search.inventory"),
|
||||
/// Permission to search containers.
|
||||
SEARCH_CONTAINER("search.container");
|
||||
|
||||
private final String permission;
|
||||
|
||||
Permissions(String permission) {
|
||||
this.permission = "openinv." + permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a {@link Permissible} has this permission.
|
||||
*
|
||||
* @param permissible the Permissible
|
||||
* @return true if the permission is granted
|
||||
*/
|
||||
public boolean hasPermission(Permissible permissible) {
|
||||
return permissible.hasPermission(permission);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.lishid.openinv.util.setting;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A per-player setting that may be enabled or disabled.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface PlayerToggle {
|
||||
|
||||
/**
|
||||
@@ -14,7 +16,7 @@ public interface PlayerToggle {
|
||||
*
|
||||
* @return the setting name
|
||||
*/
|
||||
@NotNull String getName();
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Get the state of the toggle for a particular player ID.
|
||||
@@ -22,7 +24,16 @@ public interface PlayerToggle {
|
||||
* @param uuid the player ID
|
||||
* @return true if the setting is enabled
|
||||
*/
|
||||
boolean is(@NotNull UUID uuid);
|
||||
boolean is(UUID uuid);
|
||||
|
||||
/**
|
||||
* Get the state of the toggle for a particular {@link Player},
|
||||
* accounting for permissions required to use the feature.
|
||||
*
|
||||
* @param player the player
|
||||
* @return true if the setting is enabled and the player has the required permissions
|
||||
*/
|
||||
boolean is(Player player);
|
||||
|
||||
/**
|
||||
* Set the state of the toggle for a particular player ID.
|
||||
@@ -31,6 +42,6 @@ public interface PlayerToggle {
|
||||
* @param enabled whether the setting is enabled
|
||||
* @return true if the setting changed as a result of being set
|
||||
*/
|
||||
boolean set(@NotNull UUID uuid, boolean enabled);
|
||||
boolean set(UUID uuid, boolean enabled);
|
||||
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.lishid.openinv.util.setting;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.UnmodifiableView;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -16,18 +18,31 @@ import java.util.UUID;
|
||||
/**
|
||||
* Utility class containing all of OpenInv's {@link PlayerToggle PlayerToggles}.
|
||||
*/
|
||||
@NullMarked
|
||||
public final class PlayerToggles {
|
||||
|
||||
private static final Map<String, PlayerToggle> TOGGLES = new HashMap<>();
|
||||
private static final PlayerToggle ANY = add(new MemoryToggle("AnyContainer"));
|
||||
private static final PlayerToggle SILENT = add(new MemoryToggle("SilentContainer"));
|
||||
private static final PlayerToggle ANY = add(new MemoryToggle("AnyContainer") {
|
||||
@Override
|
||||
public boolean is(Player player) {
|
||||
return is(player.getUniqueId())
|
||||
&& (Permissions.CONTAINER_ANY.hasPermission(player) || Permissions.CONTAINER_ANY_USE.hasPermission(player));
|
||||
}
|
||||
});
|
||||
private static final PlayerToggle SILENT = add(new MemoryToggle("SilentContainer") {
|
||||
@Override
|
||||
public boolean is(Player player) {
|
||||
return is(player.getUniqueId())
|
||||
&& (Permissions.CONTAINER_SILENT.hasPermission(player) || Permissions.CONTAINER_SILENT_USE.hasPermission(player));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the AnyContainer toggle.
|
||||
*
|
||||
* @return the AnyContainer toggle
|
||||
*/
|
||||
public static @NotNull PlayerToggle any() {
|
||||
public static PlayerToggle any() {
|
||||
return ANY;
|
||||
}
|
||||
|
||||
@@ -36,7 +51,7 @@ public final class PlayerToggles {
|
||||
*
|
||||
* @return the SilentContainer toggle
|
||||
*/
|
||||
public static @NotNull PlayerToggle silent() {
|
||||
public static PlayerToggle silent() {
|
||||
return SILENT;
|
||||
}
|
||||
|
||||
@@ -46,7 +61,7 @@ public final class PlayerToggles {
|
||||
* @param toggleName the name of the toggle
|
||||
* @return the toggle, or null if no such toggle exists.
|
||||
*/
|
||||
public static @Nullable PlayerToggle get(@NotNull String toggleName) {
|
||||
public static @Nullable PlayerToggle get(String toggleName) {
|
||||
PlayerToggle toggle = TOGGLES.get(toggleName);
|
||||
if (toggle == null) {
|
||||
toggle = TOGGLES.get(toggleName.toLowerCase(Locale.ENGLISH));
|
||||
@@ -59,11 +74,11 @@ public final class PlayerToggles {
|
||||
*
|
||||
* @return a view of all toggles available
|
||||
*/
|
||||
public static @UnmodifiableView @NotNull Collection<PlayerToggle> get() {
|
||||
public static @UnmodifiableView Collection<PlayerToggle> get() {
|
||||
return Collections.unmodifiableCollection(TOGGLES.values());
|
||||
}
|
||||
|
||||
private static @NotNull PlayerToggle add(@NotNull PlayerToggle toggle) {
|
||||
private static PlayerToggle add(PlayerToggle toggle) {
|
||||
TOGGLES.put(toggle.getName().toLowerCase(Locale.ENGLISH), toggle);
|
||||
return toggle;
|
||||
}
|
||||
@@ -72,28 +87,28 @@ public final class PlayerToggles {
|
||||
throw new IllegalStateException("Cannot create instance of utility class.");
|
||||
}
|
||||
|
||||
private static class MemoryToggle implements PlayerToggle {
|
||||
private static abstract class MemoryToggle implements PlayerToggle {
|
||||
|
||||
private final @NotNull Set<UUID> enabled;
|
||||
private final @NotNull String name;
|
||||
private final Set<UUID> enabled;
|
||||
private final String name;
|
||||
|
||||
private MemoryToggle(@NotNull String name) {
|
||||
private MemoryToggle(String name) {
|
||||
enabled = new HashSet<>();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getName() {
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(@NotNull UUID uuid) {
|
||||
public boolean is(UUID uuid) {
|
||||
return enabled.contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean set(@NotNull UUID uuid, boolean enabled) {
|
||||
public boolean set(UUID uuid, boolean enabled) {
|
||||
if (enabled) {
|
||||
return this.enabled.add(uuid);
|
||||
} else {
|
||||
|
||||
+25
-6
@@ -2,21 +2,40 @@ plugins {
|
||||
`java-library`
|
||||
alias(libs.plugins.paperweight) apply false
|
||||
alias(libs.plugins.shadow) apply false
|
||||
id(libs.plugins.errorprone.gradle.get().pluginId) apply false
|
||||
alias(libs.plugins.errorprone.gradle)
|
||||
}
|
||||
|
||||
// Set by Spigot module, used by Paper module to convert to Spigot's version of Mojang mappings.
|
||||
project.ext.set("craftbukkitPackage", "UNKNOWN")
|
||||
|
||||
repositories {
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
// Allow submodules to target higher Java release versions.
|
||||
// Not currently necessary (as lowest supported version is in the 1.21 range)
|
||||
// but may become relevant in the future.
|
||||
java.disableAutoTargetJvm()
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "java-library")
|
||||
apply(plugin = rootProject.libs.plugins.errorprone.gradle.get().pluginId)
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(rootProject.libs.jspecify)
|
||||
compileOnly(rootProject.libs.annotations)
|
||||
errorprone(rootProject.libs.errorprone.core)
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<JavaCompile>().configureEach {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
withType<Javadoc>().configureEach {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Task to delete ./dist where final files are output.
|
||||
tasks.register("cleanDist") {
|
||||
delete("dist")
|
||||
|
||||
@@ -6,9 +6,3 @@ repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
val libs = project.extensions.getByType(VersionCatalogsExtension::class.java).named("libs")
|
||||
implementation(libs.findLibrary("specialsource").orElseThrow())
|
||||
implementation(libs.findLibrary("errorprone-gradle").orElseThrow())
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
create("libs") {
|
||||
from(files("../gradle/libs.versions.toml"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ abstract class BuildToolsValueSource : ValueSource<File, BuildToolsValueSource.P
|
||||
abstract val exec: ExecOperations
|
||||
|
||||
interface Parameters : ValueSourceParameters {
|
||||
val mavenLocal: Property<File>
|
||||
val installDir: DirectoryProperty
|
||||
val workingDir: DirectoryProperty
|
||||
|
||||
val spigotVersion: Property<String>
|
||||
@@ -31,11 +31,11 @@ abstract class BuildToolsValueSource : ValueSource<File, BuildToolsValueSource.P
|
||||
override fun obtain(): File {
|
||||
val version = parameters.spigotVersion.get()
|
||||
val revision = parameters.spigotRevision.get()
|
||||
val installLocation = getInstallLocation(version)
|
||||
val spigotLocation = parameters.installDir.get().asFile.resolve("spigot-$version.jar")
|
||||
// If Spigot is already installed, don't reinstall.
|
||||
if (!parameters.ignoreCached.get() && installLocation.exists()) {
|
||||
if (!parameters.ignoreCached.get() && spigotLocation.exists()) {
|
||||
println("Skipping Spigot installation, $version is present")
|
||||
return installLocation
|
||||
return spigotLocation
|
||||
}
|
||||
|
||||
val buildTools = installBuildTools(parameters.workingDir.get().asFile)
|
||||
@@ -47,22 +47,29 @@ abstract class BuildToolsValueSource : ValueSource<File, BuildToolsValueSource.P
|
||||
executable = parameters.javaExecutable.get()
|
||||
workingDir = buildTools.parentFile
|
||||
classpath(buildTools)
|
||||
args = listOf("--nogui", "--rev", revision, "--remapped")
|
||||
args = listOf("--nogui", "--rev", revision)
|
||||
}.rethrowFailure()
|
||||
|
||||
val spigotBuild = buildTools.parentFile.resolve("Spigot/Spigot-Server/target/spigot-$version.jar")
|
||||
|
||||
if (!spigotBuild.exists()) {
|
||||
throw IllegalStateException(
|
||||
"Spigot build completed, but $spigotBuild does not exist! Did BuildTools change output location?"
|
||||
)
|
||||
}
|
||||
|
||||
spigotBuild.copyTo(spigotLocation, overwrite = true)
|
||||
|
||||
// Mark work for delete.
|
||||
cleanUp(buildTools.parentFile)
|
||||
|
||||
if (!installLocation.exists()) {
|
||||
if (!spigotLocation.exists()) {
|
||||
throw IllegalStateException(
|
||||
"Failed to install Spigot $version from $revision. Does the revision point to a different version?"
|
||||
)
|
||||
}
|
||||
return installLocation
|
||||
}
|
||||
|
||||
private fun getInstallLocation(version: String): File {
|
||||
return parameters.mavenLocal.get().resolve("org/spigotmc/spigot/$version/spigot-$version-remapped-mojang.jar")
|
||||
return spigotLocation
|
||||
}
|
||||
|
||||
private fun installBuildTools(workingDir: File): File {
|
||||
|
||||
@@ -12,9 +12,7 @@ abstract class SpigotDependencyExtension(
|
||||
.convention(version.map {
|
||||
it.replace("-R\\d+\\.\\d+-SNAPSHOT".toRegex(), "")
|
||||
})
|
||||
val configuration = objects.property(String::class.java)
|
||||
val classifier = objects.property(String::class.java).convention("remapped-mojang")
|
||||
val ext = objects.property(String::class.java)
|
||||
val classifier = objects.property(String::class.java).convention("")
|
||||
val java = objects.property(JavaToolchainSpec::class.java)
|
||||
val ignoreCached = objects.property(Boolean::class.java).convention(false)
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.github.jikoo.openinv
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.Bundling
|
||||
import org.gradle.api.attributes.Category
|
||||
import org.gradle.api.attributes.LibraryElements
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import java.nio.file.Paths
|
||||
|
||||
class SpigotReobf : Plugin<Project> {
|
||||
|
||||
companion object {
|
||||
const val ARTIFACT_CONFIG = "reobf"
|
||||
}
|
||||
|
||||
override fun apply(target: Project) {
|
||||
// Re-use extension from Spigot dependency declaration if available to reduce configuration requirements.
|
||||
val spigotExt = target.dependencies.extensions.findByType(SpigotDependencyExtension::class.java)
|
||||
?: target.dependencies.extensions.create(
|
||||
"spigot",
|
||||
SpigotDependencyExtension::class.java,
|
||||
target.objects
|
||||
)
|
||||
|
||||
val mvnLocal = target.repositories.mavenLocal()
|
||||
|
||||
val reobfTask = target.tasks.register<SpigotReobfTask>("reobfTask") {
|
||||
dependsOn(target.tasks.named("shadowJar"))
|
||||
// ShadowJar extends Jar, so this should be a safe way to get the result without having
|
||||
// to jump through hoops and shift around shadow declarations in the rest of the project.
|
||||
inputFile.convention(target.tasks.named<Jar>("shadowJar").get().archiveFile)
|
||||
spigotVersion.convention(spigotExt.version)
|
||||
getMavenLocal().set(Paths.get(mvnLocal.url).toFile())
|
||||
}
|
||||
|
||||
// Set up configuration for producing reobf jar.
|
||||
target.configurations.consumable(ARTIFACT_CONFIG) {
|
||||
attributes {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, target.objects.named(Category.LIBRARY))
|
||||
attribute(Usage.USAGE_ATTRIBUTE, target.objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, target.objects.named(Bundling.EXTERNAL))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, target.objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
|
||||
// Add artifact from reobf task.
|
||||
target.artifacts {
|
||||
add(ARTIFACT_CONFIG, reobfTask)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.github.jikoo.openinv
|
||||
|
||||
import net.md_5.specialsource.Jar
|
||||
import net.md_5.specialsource.JarMapping
|
||||
import net.md_5.specialsource.JarRemapper
|
||||
import net.md_5.specialsource.RemapperProcessor
|
||||
import net.md_5.specialsource.provider.JarProvider
|
||||
import net.md_5.specialsource.provider.JointProvider
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import java.io.File
|
||||
|
||||
abstract class SpigotReobfTask : org.gradle.api.tasks.bundling.Jar() {
|
||||
|
||||
@get:Input
|
||||
val spigotVersion: Property<String> = objectFactory.property(String::class.java)
|
||||
|
||||
@get:InputFile
|
||||
val inputFile: RegularFileProperty = objectFactory.fileProperty()
|
||||
|
||||
@get:Input
|
||||
val intermediaryClassifier: Property<String> = objectFactory.property(String::class.java).convention("mojang-mapped")
|
||||
|
||||
private val mavenLocal: Property<File> = objectFactory.property(File::class.java)
|
||||
|
||||
init {
|
||||
archiveClassifier.convention(SpigotReobf.ARTIFACT_CONFIG)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
override fun copy() {
|
||||
val spigotVer = spigotVersion.get()
|
||||
val inFile = inputFile.get().asFile
|
||||
val obfPath = inFile.resolveSibling(inFile.name.replace(".jar", "-${intermediaryClassifier.get()}.jar"))
|
||||
|
||||
// https://www.spigotmc.org/threads/510208/#post-4184317
|
||||
val repo = mavenLocal.get()
|
||||
val spigotDir = repo.resolve("org/spigotmc/spigot/$spigotVer/")
|
||||
val mappingDir = repo.resolve("org/spigotmc/minecraft-server/$spigotVer/")
|
||||
|
||||
// Remap original Mojang-mapped jar to obfuscated intermediary
|
||||
val mojangServer = spigotDir.resolve("spigot-$spigotVer-remapped-mojang.jar")
|
||||
val mojangMappings = mappingDir.resolve("minecraft-server-$spigotVer-maps-mojang.txt")
|
||||
remapPartial(mojangServer, mojangMappings, inFile, obfPath, true)
|
||||
|
||||
// Remap obfuscated intermediary jar to Spigot and replace original
|
||||
val obfServer = spigotDir.resolve("spigot-$spigotVer-remapped-obf.jar")
|
||||
val spigotMappings = mappingDir.resolve("minecraft-server-$spigotVer-maps-spigot.csrg")
|
||||
remapPartial(obfServer, spigotMappings, obfPath, archiveFile.get().asFile, false)
|
||||
}
|
||||
|
||||
private fun remapPartial(server: File, mapping: File, input: File, output: File, reverse: Boolean) {
|
||||
val jarMapping = JarMapping()
|
||||
jarMapping.loadMappings(mapping.path, reverse, false, null, null)
|
||||
|
||||
val inheritance = JointProvider()
|
||||
jarMapping.setFallbackInheritanceProvider(inheritance)
|
||||
|
||||
// Equivalent of --live with server jar on classpath.
|
||||
val serverJar = Jar.init(server)
|
||||
inheritance.add(JarProvider(serverJar))
|
||||
|
||||
val inputJar = Jar.init(input)
|
||||
inheritance.add(JarProvider(inputJar))
|
||||
|
||||
// Remap reflective access.
|
||||
val preprocessor = RemapperProcessor(null, jarMapping, null)
|
||||
|
||||
val remapper = JarRemapper(preprocessor, jarMapping, null)
|
||||
remapper.remapJar(inputJar, output, emptySet())
|
||||
|
||||
serverJar.close()
|
||||
inputJar.close()
|
||||
}
|
||||
|
||||
@Internal
|
||||
internal fun getMavenLocal(): Property<File> {
|
||||
return mavenLocal
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,7 @@ import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService
|
||||
import org.gradle.kotlin.dsl.create
|
||||
import java.nio.file.Paths
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class SpigotSetup : Plugin<Project> {
|
||||
@@ -24,17 +23,15 @@ abstract class SpigotSetup : Plugin<Project> {
|
||||
target.objects
|
||||
)
|
||||
|
||||
val mvnLocal = target.repositories.mavenLocal()
|
||||
|
||||
target.afterEvaluate {
|
||||
// Get Java requirements, defaulting to version used for compilation.
|
||||
spigotExt.java.convention(target.extensions.getByType(JavaPluginExtension::class.java).toolchain)
|
||||
val launcher = javaToolchainService.launcherFor(spigotExt.java.get()).get()
|
||||
|
||||
// Install Spigot with BuildTools.
|
||||
target.providers.of(BuildToolsValueSource::class.java) {
|
||||
val spigot: File = target.providers.of(BuildToolsValueSource::class.java) {
|
||||
parameters {
|
||||
mavenLocal.set(Paths.get(mvnLocal.url).toFile())
|
||||
installDir.set(target.gradle.gradleUserHomeDir.resolve("caches/spigot"))
|
||||
workingDir.set(target.layout.buildDirectory.dir("tmp/buildtools"))
|
||||
spigotVersion.set(spigotExt.version)
|
||||
spigotRevision.set(spigotExt.revision)
|
||||
@@ -45,14 +42,7 @@ abstract class SpigotSetup : Plugin<Project> {
|
||||
}.get()
|
||||
|
||||
// Add Spigot dependency.
|
||||
val dependency = target.dependencies.create(
|
||||
"org.spigotmc",
|
||||
"spigot",
|
||||
spigotExt.version.get(),
|
||||
spigotExt.configuration.orNull,
|
||||
spigotExt.classifier.orNull,
|
||||
spigotExt.ext.orNull
|
||||
)
|
||||
val dependency = target.dependencies.create(files(spigot))
|
||||
target.dependencies.add("compileOnly", dependency)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
id("net.ltgt.errorprone")
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
val libs = versionCatalogs.named("libs")
|
||||
compileOnly(libs.findLibrary("annotations").orElseThrow())
|
||||
compileOnly(libs.findLibrary("spigotapi").orElseThrow())
|
||||
errorprone(libs.findLibrary("errorprone-core").orElseThrow())
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<JavaCompile>().configureEach {
|
||||
options.release = 21
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
withType<Javadoc>().configureEach {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -1,5 +1,17 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
repositories {
|
||||
maven("https://hub.spigotmc.org/nexus/content/groups/public/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.spigotapi)
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.release = 21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.github.jikoo.openinv.internal;
|
||||
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public interface Accessor {
|
||||
|
||||
PlayerManager getPlayerManager();
|
||||
|
||||
IAnySilentContainer getAnySilentContainer();
|
||||
|
||||
ISpecialPlayerInventory createPlayerInventory(Player player);
|
||||
|
||||
ISpecialEnderChest createEnderChest(Player player);
|
||||
|
||||
<T extends ISpecialInventory> @Nullable T get(Inventory bukkitInventory, Class<T> clazz);
|
||||
|
||||
void reload(ConfigurationSection config);
|
||||
|
||||
}
|
||||
+8
-6
@@ -14,14 +14,16 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.internal;
|
||||
package com.github.jikoo.openinv.internal;
|
||||
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public interface PlayerManager {
|
||||
|
||||
/**
|
||||
@@ -32,14 +34,14 @@ public interface PlayerManager {
|
||||
* @param offline the OfflinePlayer
|
||||
* @return the Player loaded
|
||||
*/
|
||||
@Nullable Player loadPlayer(@NotNull OfflinePlayer offline);
|
||||
@Nullable Player loadPlayer(OfflinePlayer offline);
|
||||
|
||||
/**
|
||||
* Creates a new Player from an existing one that will function slightly better offline.
|
||||
*
|
||||
* @return the Player
|
||||
*/
|
||||
@NotNull Player inject(@NotNull Player player);
|
||||
Player inject(Player player);
|
||||
|
||||
/**
|
||||
* Opens an ISpecialInventory for a Player.
|
||||
@@ -49,6 +51,6 @@ public interface PlayerManager {
|
||||
*
|
||||
* @return the InventoryView opened
|
||||
*/
|
||||
@Nullable InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory, boolean viewOnly);
|
||||
@Nullable InventoryView openInventory(Player player, ISpecialInventory inventory, boolean viewOnly);
|
||||
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package com.github.jikoo.openinv.internal.container;
|
||||
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import org.bukkit.block.Barrel;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.EnderChest;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Chest;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@NullMarked
|
||||
public abstract class AnySilentContainerBase implements IAnySilentContainer {
|
||||
|
||||
public enum StateType {
|
||||
ENDER_CHEST,
|
||||
SHULKER_BOX,
|
||||
CHEST,
|
||||
BARREL,
|
||||
OTHER
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyContainerNeeded(Block block) {
|
||||
return isAnyContainerNeeded(getStateType(block), block);
|
||||
}
|
||||
|
||||
protected boolean isAnyContainerNeeded(StateType material, Block block) {
|
||||
return switch (material) {
|
||||
// Enderchests require a non-occluding block on top to open.
|
||||
case ENDER_CHEST -> block.getRelative(0, 1, 0).getType().isOccluding();
|
||||
// Shulker boxes require half a block clear in the direction they open.
|
||||
case SHULKER_BOX -> isShulkerBlocked(block);
|
||||
// Chests require that the block above not be occluding or occupied by a cat.
|
||||
case CHEST -> isChestBlocked(block);
|
||||
// Barrels need silent but not any. All others unsupported.
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChestBlocked(Block block) {
|
||||
if (IAnySilentContainer.super.isChestBlocked(block)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Chest chest) || chest.getType() == Chest.Type.SINGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockFace relativeFace = switch (chest.getFacing()) {
|
||||
case NORTH -> chest.getType() == Chest.Type.RIGHT ? BlockFace.WEST : BlockFace.EAST;
|
||||
case EAST -> chest.getType() == Chest.Type.RIGHT ? BlockFace.NORTH : BlockFace.SOUTH;
|
||||
case SOUTH -> chest.getType() == Chest.Type.RIGHT ? BlockFace.EAST : BlockFace.WEST;
|
||||
case WEST -> chest.getType() == Chest.Type.RIGHT ? BlockFace.SOUTH : BlockFace.NORTH;
|
||||
default -> BlockFace.SELF;
|
||||
};
|
||||
Block relative = block.getRelative(relativeFace);
|
||||
|
||||
if (relative.getType() != block.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockData relativeData = relative.getBlockData();
|
||||
if (!(relativeData instanceof Chest relativeChest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (relativeChest.getFacing() != chest.getFacing()
|
||||
|| relativeChest.getType() != (chest.getType() == Chest.Type.RIGHT ? Chest.Type.LEFT : Chest.Type.RIGHT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IAnySilentContainer.super.isChestBlocked(relative);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnySilentContainer(Block block) {
|
||||
return isAnySilentContainer(getState(block));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnySilentContainer(Inventory inventory) {
|
||||
return isAnySilentContainer(getHolder(inventory));
|
||||
}
|
||||
|
||||
protected StateType getStateType(Block block) {
|
||||
return switch (getState(block)) {
|
||||
case Barrel ignored -> StateType.BARREL;
|
||||
case EnderChest ignored -> StateType.ENDER_CHEST;
|
||||
case ShulkerBox ignored -> StateType.SHULKER_BOX;
|
||||
case org.bukkit.block.Chest ignored -> StateType.CHEST;
|
||||
default -> StateType.OTHER;
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract BlockState getState(Block block);
|
||||
|
||||
protected abstract @Nullable InventoryHolder getHolder(Inventory inventory);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.github.jikoo.openinv.internal.container;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public interface InternalOwned<T> {
|
||||
|
||||
T getOwnerHandle();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.github.jikoo.openinv.internal.container;
|
||||
|
||||
public interface ViewOnly {
|
||||
}
|
||||
+12
-15
@@ -1,53 +1,50 @@
|
||||
package com.lishid.openinv.internal.common.container.slot;
|
||||
package com.github.jikoo.openinv.internal.container.slot;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* An interface defining behaviors for entries in a {@link Container}. Used to reduce duplicate content reordering.
|
||||
* An interface defining behaviors for entries in a {@link net.minecraft.world.Container Container}. Used to reduce duplicate content reordering.
|
||||
*/
|
||||
public interface Content {
|
||||
@NullMarked
|
||||
public interface Content<P, I, C, S> {
|
||||
|
||||
/**
|
||||
* Update internal holder.
|
||||
*
|
||||
* @param holder the new holder
|
||||
*/
|
||||
void setHolder(@NotNull ServerPlayer holder);
|
||||
void setHolder(P holder);
|
||||
|
||||
/**
|
||||
* Get the current item.
|
||||
*
|
||||
* @return the current item
|
||||
*/
|
||||
ItemStack get();
|
||||
I get();
|
||||
|
||||
/**
|
||||
* Remove the current item.
|
||||
*
|
||||
* @return the current item
|
||||
*/
|
||||
ItemStack remove();
|
||||
I remove();
|
||||
|
||||
/**
|
||||
* Remove some of the current item.
|
||||
*
|
||||
* @return the current item
|
||||
*/
|
||||
ItemStack removePartial(int amount);
|
||||
I removePartial(int amount);
|
||||
|
||||
/**
|
||||
* Set the current item. If slot is currently not usable, will drop item instead.
|
||||
*
|
||||
* @param itemStack the item to set
|
||||
*/
|
||||
void set(ItemStack itemStack);
|
||||
void set(I itemStack);
|
||||
|
||||
/**
|
||||
* Get a {@link Slot} for use in a {@link net.minecraft.world.inventory.AbstractContainerMenu ContainerMenu}. Will
|
||||
* Get a {@link net.minecraft.world.inventory.Slot Slot} for use in a {@link net.minecraft.world.inventory.AbstractContainerMenu ContainerMenu}. Will
|
||||
* impose any specific restrictions to insertion or removal.
|
||||
*
|
||||
* @param container the backing container
|
||||
@@ -56,7 +53,7 @@ public interface Content {
|
||||
* @param y clientside y dimension from top left of inventory, not used
|
||||
* @return a menu slot
|
||||
*/
|
||||
Slot asSlot(Container container, int slot, int x, int y);
|
||||
S asSlot(C container, int slot, int x, int y);
|
||||
|
||||
/**
|
||||
* Get a loose Bukkit translation of what this slot stores. For example, any slot that drops items at the owner rather
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.github.jikoo.openinv.internal.container.slot;
|
||||
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
@NullMarked
|
||||
public interface InventoryFactory<P, I, C, S, E> {
|
||||
|
||||
Content<P, I, C, S> newCrafting(P holder, int index);
|
||||
|
||||
Content<P, I, C, S> newCraftingResult(P holder);
|
||||
|
||||
Content<P, I, C, S> newCursor(P holder);
|
||||
|
||||
Content<P, I, C, S> newDrop(P holder);
|
||||
|
||||
Content<P, I, C, S> newEquipment(P holder, E equipmentSlot);
|
||||
|
||||
Content<P, I, C, S> newList(P holder, int index, InventoryType.SlotType slotType, Function<P, List<I>> listSupplier);
|
||||
|
||||
Content<P, I, C, S> newOffHand(P holder);
|
||||
|
||||
Content<P, I, C, S> newViewOnly(P holder);
|
||||
|
||||
Content<P, I, C, S> newViewOnly(P holder, I itemStack);
|
||||
|
||||
S wrapViewOnly(S wrapped);
|
||||
|
||||
ItemStack asBukkitMirror(I itemStack);
|
||||
|
||||
}
|
||||
+24
-41
@@ -1,20 +1,4 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2022 lishid. All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.util.lang;
|
||||
package com.github.jikoo.openinv.lang;
|
||||
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
@@ -25,8 +9,8 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
@@ -44,9 +28,8 @@ import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* A simple language manager supporting both custom and bundled languages.
|
||||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
@NullMarked
|
||||
public class LanguageManager {
|
||||
|
||||
private final Plugin plugin;
|
||||
@@ -54,7 +37,7 @@ public class LanguageManager {
|
||||
private final String defaultLocale;
|
||||
private final Map<String, YamlConfiguration> locales;
|
||||
|
||||
public LanguageManager(@NotNull Plugin plugin, @NotNull String defaultLocale) {
|
||||
public LanguageManager(Plugin plugin, String defaultLocale) {
|
||||
this.plugin = plugin;
|
||||
this.defaultLocale = defaultLocale;
|
||||
this.locales = new HashMap<>();
|
||||
@@ -72,7 +55,7 @@ public class LanguageManager {
|
||||
getOrLoadLocale(defaultLocale);
|
||||
}
|
||||
|
||||
private @NotNull YamlConfiguration getOrLoadLocale(@NotNull String locale) {
|
||||
private YamlConfiguration getOrLoadLocale(String locale) {
|
||||
YamlConfiguration loaded = locales.get(locale);
|
||||
if (loaded != null) {
|
||||
return loaded;
|
||||
@@ -110,7 +93,7 @@ public class LanguageManager {
|
||||
return localeConfig;
|
||||
}
|
||||
|
||||
private @NotNull LangLocation bestMatch(@NotNull String locale, @Nullable LangLocation initial) {
|
||||
private LangLocation bestMatch(String locale, @Nullable LangLocation initial) {
|
||||
File file = new File(folder, locale + ".yml");
|
||||
InputStream bundled = plugin.getResource("locale/" + locale + ".yml");
|
||||
|
||||
@@ -132,7 +115,7 @@ public class LanguageManager {
|
||||
return bestMatch(locale.substring(0, lastSeparator), initial);
|
||||
}
|
||||
|
||||
private @NotNull YamlConfiguration loadLocale(@NotNull LangLocation lang) {
|
||||
private YamlConfiguration loadLocale(LangLocation lang) {
|
||||
YamlConfiguration localeConfigDefaults;
|
||||
if (lang.bundled == null) {
|
||||
localeConfigDefaults = new YamlConfiguration();
|
||||
@@ -195,7 +178,7 @@ public class LanguageManager {
|
||||
return localeConfig;
|
||||
}
|
||||
|
||||
private void addTranslationFallthrough(@NotNull LangLocation location, @NotNull YamlConfiguration localeConfig) {
|
||||
private void addTranslationFallthrough(LangLocation location, YamlConfiguration localeConfig) {
|
||||
YamlConfiguration defaultLocaleConfig = locales.get(defaultLocale);
|
||||
|
||||
// Get missing keys. Keys that already have a guess value are not new and don't need to trigger another write.
|
||||
@@ -222,9 +205,9 @@ public class LanguageManager {
|
||||
localeConfig.setDefaults(defaultLocaleConfig);
|
||||
}
|
||||
|
||||
private @NotNull List<String> getMissingKeys(
|
||||
@NotNull Configuration configurationDefault,
|
||||
@NotNull Predicate<String> nodeSetPredicate
|
||||
private List<String> getMissingKeys(
|
||||
Configuration configurationDefault,
|
||||
Predicate<String> nodeSetPredicate
|
||||
) {
|
||||
List<String> missingKeys = new ArrayList<>();
|
||||
for (String key : configurationDefault.getKeys(true)) {
|
||||
@@ -236,7 +219,7 @@ public class LanguageManager {
|
||||
return missingKeys;
|
||||
}
|
||||
|
||||
public @Nullable String getValue(@NotNull String key, @Nullable String locale) {
|
||||
public @Nullable String getValue(String key, @Nullable String locale) {
|
||||
String value = getOrLoadLocale(locale == null ? defaultLocale : locale.toLowerCase(Locale.ENGLISH)).getString(key);
|
||||
if (value == null || value.isBlank()) {
|
||||
return null;
|
||||
@@ -248,9 +231,9 @@ public class LanguageManager {
|
||||
}
|
||||
|
||||
public @Nullable String getValue(
|
||||
@NotNull String key,
|
||||
String key,
|
||||
@Nullable String locale,
|
||||
Replacement @NotNull ... replacements
|
||||
Replacement... replacements
|
||||
) {
|
||||
String value = getValue(key, locale);
|
||||
|
||||
@@ -265,19 +248,19 @@ public class LanguageManager {
|
||||
return value;
|
||||
}
|
||||
|
||||
public @Nullable String getLocalizedMessage(@NotNull CommandSender sender, @NotNull String key) {
|
||||
public @Nullable String getLocalizedMessage(CommandSender sender, String key) {
|
||||
return getValue(key, getLocale(sender));
|
||||
}
|
||||
|
||||
public @Nullable String getLocalizedMessage(
|
||||
@NotNull CommandSender sender,
|
||||
@NotNull String key,
|
||||
Replacement @NotNull ... replacements
|
||||
CommandSender sender,
|
||||
String key,
|
||||
Replacement... replacements
|
||||
) {
|
||||
return getValue(key, getLocale(sender), replacements);
|
||||
}
|
||||
|
||||
private @NotNull String getLocale(@NotNull CommandSender sender) {
|
||||
private String getLocale(CommandSender sender) {
|
||||
if (sender instanceof Player player) {
|
||||
return player.getLocale();
|
||||
} else {
|
||||
@@ -285,7 +268,7 @@ public class LanguageManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(@NotNull CommandSender sender, @NotNull String key) {
|
||||
public void sendMessage(CommandSender sender, String key) {
|
||||
String message = getLocalizedMessage(sender, key);
|
||||
|
||||
if (message != null && !message.isEmpty()) {
|
||||
@@ -293,7 +276,7 @@ public class LanguageManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(@NotNull CommandSender sender, @NotNull String key, Replacement @NotNull ... replacements) {
|
||||
public void sendMessage(CommandSender sender, String key, Replacement... replacements) {
|
||||
String message = getLocalizedMessage(sender, key, replacements);
|
||||
|
||||
if (message != null && !message.isEmpty()) {
|
||||
@@ -301,7 +284,7 @@ public class LanguageManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSystemMessage(@NotNull Player player, @NotNull String key) {
|
||||
public void sendSystemMessage(Player player, String key) {
|
||||
String message = getLocalizedMessage(player, key);
|
||||
|
||||
if (message == null) {
|
||||
@@ -321,6 +304,6 @@ public class LanguageManager {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacy(message));
|
||||
}
|
||||
|
||||
private record LangLocation(@NotNull String locale, @NotNull File file, @Nullable InputStream bundled) {}
|
||||
private record LangLocation(String locale, File file, @Nullable InputStream bundled) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.github.jikoo.openinv.lang;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
/**
|
||||
* A data holder for string replacement in translations.
|
||||
*
|
||||
* @param placeholder the placeholder to be replaced
|
||||
* @param value the value to insert
|
||||
*/
|
||||
@NullMarked
|
||||
public record Replacement(String placeholder, String value) {
|
||||
|
||||
}
|
||||
+14
-17
@@ -1,5 +1,6 @@
|
||||
package com.lishid.openinv.util;
|
||||
package com.github.jikoo.openinv.util;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.helpers.LegacyAbstractLogger;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
@@ -14,6 +15,7 @@ import java.util.logging.Logger;
|
||||
* An adapter for wrapping a {@link java.util.logging.Logger} as a {@link org.slf4j.Logger}.
|
||||
* <br>Largely based on {@code JDK14LoggerAdapter}, which is not present at runtime.
|
||||
*/
|
||||
@NullMarked
|
||||
public class JulLoggerAdapter extends LegacyAbstractLogger implements LocationAwareLogger {
|
||||
|
||||
private final Logger wrapped;
|
||||
@@ -55,22 +57,17 @@ public class JulLoggerAdapter extends LegacyAbstractLogger implements LocationAw
|
||||
}
|
||||
|
||||
private void addSource(String fqcn, LogRecord logRecord) {
|
||||
// TODO stackwalker?
|
||||
StackTraceElement[] trace = new Throwable().getStackTrace();
|
||||
int maxElements = 12;
|
||||
int lastIgnored = maxElements;
|
||||
// Start from 2; 0 is above and 1 is caller of internal method.
|
||||
for (int i = 2; i < maxElements; ++i) {
|
||||
if (isIgnored(trace[i].getClassName(), fqcn)) {
|
||||
lastIgnored = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastIgnored < maxElements - 1) {
|
||||
StackTraceElement caller = trace[lastIgnored + 1];
|
||||
logRecord.setSourceClassName(caller.getClassName());
|
||||
logRecord.setSourceMethodName(caller.getMethodName());
|
||||
}
|
||||
StackWalker.getInstance().walk(stream -> stream
|
||||
// Start at index 2 - this is an internal method, so we want at least the caller's caller.
|
||||
.skip(2)
|
||||
// Walk at maximum 10 frames.
|
||||
.limit(10)
|
||||
.filter(frame -> isIgnored(frame.getClassName(), fqcn))
|
||||
.findFirst()
|
||||
).ifPresent(frame -> {
|
||||
logRecord.setSourceClassName(frame.getClassName());
|
||||
logRecord.setSourceMethodName(frame.getMethodName());
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isIgnored(String className, String fqcn) {
|
||||
+4
-18
@@ -1,28 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2021 lishid. All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.github.jikoo.openinv.util;
|
||||
|
||||
package com.lishid.openinv.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* A utility for making reflection easier.
|
||||
*/
|
||||
@NullMarked
|
||||
public final class ReflectionHelper {
|
||||
|
||||
/**
|
||||
@@ -6,24 +6,25 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Construct and call events.
|
||||
*/
|
||||
@NullMarked
|
||||
public final class OpenEvents {
|
||||
|
||||
public static boolean saveCancelled(@NotNull Player player) {
|
||||
public static boolean saveCancelled(Player player) {
|
||||
return call(new PlayerSaveEvent(player));
|
||||
}
|
||||
|
||||
public static boolean saveCancelled(@NotNull ISpecialInventory inventory) {
|
||||
public static boolean saveCancelled(ISpecialInventory inventory) {
|
||||
return call(new OpenPlayerSaveEvent((Player) inventory.getPlayer(), inventory));
|
||||
}
|
||||
|
||||
public static void notifyPlayerToggle(@NotNull PlayerToggle toggle, @NotNull UUID uuid, boolean state) {
|
||||
public static void notifyPlayerToggle(PlayerToggle toggle, UUID uuid, boolean state) {
|
||||
Bukkit.getPluginManager().callEvent(new PlayerToggledEvent(toggle, uuid, state));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.lishid.openinv.internal;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Accessor {
|
||||
|
||||
@NotNull
|
||||
PlayerManager getPlayerManager();
|
||||
|
||||
@NotNull IAnySilentContainer getAnySilentContainer();
|
||||
|
||||
@NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player);
|
||||
|
||||
@NotNull ISpecialEnderChest createEnderChest(@NotNull Player player);
|
||||
|
||||
<T extends ISpecialInventory> @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class<T> clazz);
|
||||
|
||||
void reload(@NotNull ConfigurationSection config);
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package com.lishid.openinv.internal;
|
||||
|
||||
import org.bukkit.block.Barrel;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.EnderChest;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Chest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public abstract class AnySilentContainerBase implements IAnySilentContainer {
|
||||
|
||||
private static final @Nullable Method BLOCK_GET_STATE_BOOLEAN;
|
||||
|
||||
static {
|
||||
@Nullable Method getState;
|
||||
try {
|
||||
//noinspection JavaReflectionMemberAccess
|
||||
getState = Block.class.getMethod("getState", boolean.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
getState = null;
|
||||
}
|
||||
BLOCK_GET_STATE_BOOLEAN = getState;
|
||||
}
|
||||
|
||||
private static BlockState getBlockState(Block block) {
|
||||
// Paper: Get state without snapshotting.
|
||||
if (BLOCK_GET_STATE_BOOLEAN != null) {
|
||||
try {
|
||||
return (BlockState) BLOCK_GET_STATE_BOOLEAN.invoke(block, false);
|
||||
} catch (ReflectiveOperationException ignored) {
|
||||
// If we encounter an issue, fall through to regular snapshotting method.
|
||||
}
|
||||
}
|
||||
return block.getState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyContainerNeeded(@NotNull Block block) {
|
||||
BlockState blockState = getBlockState(block);
|
||||
|
||||
// Barrels do not require AnyContainer.
|
||||
if (blockState instanceof Barrel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enderchests require a non-occluding block on top to open.
|
||||
if (blockState instanceof EnderChest) {
|
||||
return block.getRelative(0, 1, 0).getType().isOccluding();
|
||||
}
|
||||
|
||||
// Shulker boxes require half a block clear in the direction they open.
|
||||
if (blockState instanceof ShulkerBox) {
|
||||
return isShulkerBlocked(block);
|
||||
}
|
||||
|
||||
if (!(blockState instanceof org.bukkit.block.Chest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isChestBlocked(block)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Chest chest) || chest.getType() == Chest.Type.SINGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockFace relativeFace = switch (chest.getFacing()) {
|
||||
case NORTH -> chest.getType() == Chest.Type.RIGHT ? BlockFace.WEST : BlockFace.EAST;
|
||||
case EAST -> chest.getType() == Chest.Type.RIGHT ? BlockFace.NORTH : BlockFace.SOUTH;
|
||||
case SOUTH -> chest.getType() == Chest.Type.RIGHT ? BlockFace.EAST : BlockFace.WEST;
|
||||
case WEST -> chest.getType() == Chest.Type.RIGHT ? BlockFace.SOUTH : BlockFace.NORTH;
|
||||
default -> BlockFace.SELF;
|
||||
};
|
||||
Block relative = block.getRelative(relativeFace);
|
||||
|
||||
if (relative.getType() != block.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockData relativeData = relative.getBlockData();
|
||||
if (!(relativeData instanceof Chest relativeChest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (relativeChest.getFacing() != chest.getFacing()
|
||||
|| relativeChest.getType() != (chest.getType() == Chest.Type.RIGHT ? Chest.Type.LEFT : Chest.Type.RIGHT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isChestBlocked(relative);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnySilentContainer(@NotNull Block block) {
|
||||
return isAnySilentContainer(getBlockState(block));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.lishid.openinv.internal;
|
||||
|
||||
public interface InternalOwned<T> {
|
||||
|
||||
T getOwnerHandle();
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.lishid.openinv.internal;
|
||||
|
||||
public interface ViewOnly {
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2022 lishid. All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.util;
|
||||
|
||||
import org.bukkit.permissions.Permissible;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum Permissions {
|
||||
|
||||
INVENTORY_OPEN_SELF("inventory.open.self"),
|
||||
INVENTORY_OPEN_OTHER("inventory.open.other"),
|
||||
INVENTORY_EDIT_SELF("inventory.edit.self"),
|
||||
INVENTORY_EDIT_OTHER("inventory.edit.other"),
|
||||
INVENTORY_SLOT_HEAD_ANY("inventory.slot.head.any"),
|
||||
INVENTORY_SLOT_CHEST_ANY("inventory.slot.chest.any"),
|
||||
INVENTORY_SLOT_LEGS_ANY("inventory.slot.legs.any"),
|
||||
INVENTORY_SLOT_FEET_ANY("inventory.slot.feet.any"),
|
||||
INVENTORY_SLOT_DROP("inventory.slot.drop"),
|
||||
|
||||
ENDERCHEST_OPEN_SELF("enderchest.open.self"),
|
||||
ENDERCHEST_OPEN_OTHER("enderchest.open.other"),
|
||||
ENDERCHEST_EDIT_SELF("enderchest.edit.self"),
|
||||
ENDERCHEST_EDIT_OTHER("enderchest.edit.other"),
|
||||
|
||||
CLEAR_SELF("clear.self"),
|
||||
CLEAR_OTHER("clear.other"),
|
||||
|
||||
ACCESS_CROSSWORLD("access.crossworld"),
|
||||
ACCESS_OFFLINE("access.offline"),
|
||||
ACCESS_ONLINE("access.online"),
|
||||
|
||||
SPECTATE_CLICK("spectate.click"),
|
||||
|
||||
CONTAINER_ANY("container.any"),
|
||||
CONTAINER_SILENT("container.silent"),
|
||||
SEARCH_INVENTORY("search.inventory"),
|
||||
SEARCH_CONTAINER("search.container");
|
||||
|
||||
private final String permission;
|
||||
|
||||
Permissions(String permission) {
|
||||
this.permission = "openinv." + permission;
|
||||
}
|
||||
|
||||
public boolean hasPermission(@NotNull Permissible permissible) {
|
||||
return permissible.hasPermission(permission);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2022 lishid. All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.util.lang;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A data holder for string replacement in translations.
|
||||
*
|
||||
* @param placeholder the placeholder to be replaced
|
||||
* @param value the value to insert
|
||||
*/
|
||||
public record Replacement(@NotNull String placeholder, @NotNull String value) {
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Project meta
|
||||
group=com.lishid.openinv
|
||||
version=5.1.13
|
||||
version=5.3.5
|
||||
description=A Bukkit plugin for opening normally-inaccessible inventories.
|
||||
|
||||
# Gradle configuration
|
||||
|
||||
+17
-10
@@ -1,24 +1,31 @@
|
||||
[versions]
|
||||
spigotapi = "1.21.5-R0.1-SNAPSHOT"
|
||||
specialsource = "1.11.5"
|
||||
spigotapi = "1.21.3-R0.1-SNAPSHOT"
|
||||
planarwrappers = "3.3.0"
|
||||
annotations = "26.0.2"
|
||||
paperweight = "2.0.0-beta.17"
|
||||
shadow = "8.3.8"
|
||||
jspecify = "1.0.1"
|
||||
annotations = "26.1.0"
|
||||
paperweight = "2.0.0-beta.21"
|
||||
shadow = "9.6.1"
|
||||
folia-scheduler-wrapper = "v0.0.3"
|
||||
errorprone-core = "2.39.0"
|
||||
errorprone-gradle = "4.2.0"
|
||||
slf4j = "2.0.17"
|
||||
errorprone-core = "2.50.0"
|
||||
errorprone-gradle = "5.1.1"
|
||||
slf4j = "2.0.20"
|
||||
sqlite-jdbc = "3.49.1.0"
|
||||
mockito-core = "5.24.0"
|
||||
junit-jupiter = "6.1.3"
|
||||
hamcrest = "3.0"
|
||||
|
||||
[libraries]
|
||||
spigotapi = { module = "org.spigotmc:spigot-api", version.ref = "spigotapi" }
|
||||
specialsource = { module = "net.md-5:SpecialSource", version.ref = "specialsource" }
|
||||
planarwrappers = { module = "com.github.jikoo:planarwrappers", version.ref = "planarwrappers" }
|
||||
jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" }
|
||||
annotations = { module = "org.jetbrains:annotations", version.ref = "annotations" }
|
||||
folia-scheduler-wrapper = { module = "com.github.NahuLD.folia-scheduler-wrapper:folia-scheduler-wrapper", version.ref = "folia-scheduler-wrapper" }
|
||||
errorprone-core = { module = "com.google.errorprone:error_prone_core", version.ref = "errorprone-core" }
|
||||
errorprone-gradle = { module = "net.ltgt.gradle:gradle-errorprone-plugin", version.ref = "errorprone-gradle" }
|
||||
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
|
||||
sqlite-jdbc = { module = "org.xerial:sqlite-jdbc", version.ref = "sqlite-jdbc" }
|
||||
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito-core" }
|
||||
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
|
||||
hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "hamcrest" }
|
||||
|
||||
[plugins]
|
||||
paperweight = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" }
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+3
-1
@@ -1,7 +1,9 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.0-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
# gradlew start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
@@ -29,7 +29,7 @@
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
# ksh gradlew
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
@@ -57,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -114,7 +114,6 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -172,7 +171,6 @@ fi
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
@@ -205,15 +203,14 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+112
-94
@@ -1,94 +1,112 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem gradlew startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
@rem Catch executions from older scripts and ensure they exit cleanly.
|
||||
@rem This can be removed once we can be reasonably confident that few people
|
||||
@rem will be migrating directly to this new wrapper.
|
||||
goto afterSafetyNet
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
goto exitWithErrorLevel
|
||||
:afterSafetyNet
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
1>&2 echo.
|
||||
1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
1>&2 echo.
|
||||
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
|
||||
1>&2 echo location of your Java installation.
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
goto exitWithErrorLevel
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
1>&2 echo.
|
||||
1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
1>&2 echo.
|
||||
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
|
||||
1>&2 echo location of your Java installation.
|
||||
|
||||
"%COMSPEC%" /c exit 1
|
||||
goto exitWithErrorLevel
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
|
||||
|
||||
@rem Execute gradlew
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
|
||||
|
||||
@rem This label must not be changed. We rely on old scripts being able to jump to this point.
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
@@ -1,60 +0,0 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
plugins {
|
||||
`openinv-base`
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
//tasks {
|
||||
// withType<JavaCompile> {
|
||||
// // OpenPlayer unchecked warning is due to superclass' messy inheritance and legacy methods.
|
||||
// options.compilerArgs.add("-Xlint:unchecked")
|
||||
// // PlayerManager uses "deprecated" method matching vanilla to support legacy save data.
|
||||
// // While vanilla still feels that it is appropriate to use in the load process, we will too.
|
||||
// options.compilerArgs.add("-Xlint:deprecation")
|
||||
// }
|
||||
//}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") {
|
||||
val paper = candidates.firstOrNull {
|
||||
it.id.let { id ->
|
||||
id is ModuleComponentIdentifier && id.module == "paper-api"
|
||||
}
|
||||
}
|
||||
if (paper != null) {
|
||||
select(paper)
|
||||
}
|
||||
because("module is written for Paper servers")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi"))
|
||||
implementation(project(":openinvcommon"))
|
||||
|
||||
paperweight.paperDevBundle("1.21.8-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
val spigot = tasks.register<ShadowJar>("spigotRelocations") {
|
||||
dependsOn(tasks.jar)
|
||||
from(sourceSets.main.get().output)
|
||||
relocate("com.lishid.openinv.internal.common", "com.lishid.openinv.internal.reobf")
|
||||
relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.${rootProject.extra["craftbukkitPackage"]}")
|
||||
archiveClassifier = "spigot"
|
||||
}
|
||||
|
||||
configurations {
|
||||
consumable("spigotRelocated") {
|
||||
attributes {
|
||||
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
add("spigotRelocated", spigot)
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
package com.lishid.openinv.internal.common;
|
||||
|
||||
import com.lishid.openinv.internal.Accessor;
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.internal.common.container.AnySilentContainer;
|
||||
import com.lishid.openinv.internal.common.container.OpenEnderChest;
|
||||
import com.lishid.openinv.internal.common.container.OpenInventory;
|
||||
import com.lishid.openinv.internal.common.container.slot.placeholder.PlaceholderLoader;
|
||||
import com.lishid.openinv.internal.common.player.PlayerManager;
|
||||
import com.lishid.openinv.util.lang.LanguageManager;
|
||||
import net.minecraft.world.Container;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class InternalAccessor implements Accessor {
|
||||
|
||||
protected final @NotNull Logger logger;
|
||||
private final @NotNull PlayerManager manager;
|
||||
private final @NotNull AnySilentContainer anySilentContainer;
|
||||
|
||||
public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) {
|
||||
this.logger = logger;
|
||||
manager = new PlayerManager(logger);
|
||||
anySilentContainer = new AnySilentContainer(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerManager getPlayerManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IAnySilentContainer getAnySilentContainer() {
|
||||
return anySilentContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) {
|
||||
return new OpenInventory(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) {
|
||||
return new OpenEnderChest(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ISpecialInventory> @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class<T> clazz) {
|
||||
if (!(bukkitInventory instanceof CraftInventory craftInventory)) {
|
||||
return null;
|
||||
}
|
||||
Container container = craftInventory.getInventory();
|
||||
if (clazz.isInstance(container)) {
|
||||
return clazz.cast(container);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(@NotNull ConfigurationSection config) {
|
||||
ConfigurationSection placeholders = config.getConfigurationSection("placeholders");
|
||||
try {
|
||||
// Reset placeholders to defaults and try to load configuration.
|
||||
new PlaceholderLoader().load(placeholders);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.lishid.openinv.internal.common.container.bukkit;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.OpenInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenPlayerInventorySelf extends OpenPlayerInventory {
|
||||
|
||||
private final int offset;
|
||||
|
||||
public OpenPlayerInventorySelf(@NotNull OpenInventory inventory, int offset) {
|
||||
super(inventory);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int index) {
|
||||
return super.getItem(offset + index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int index, ItemStack item) {
|
||||
super.setItem(offset + index, item);
|
||||
}
|
||||
|
||||
}
|
||||
-490
@@ -1,490 +0,0 @@
|
||||
package com.lishid.openinv.internal.common.container.menu;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.InternalOwned;
|
||||
import com.lishid.openinv.internal.common.container.bukkit.OpenDummyInventory;
|
||||
import com.lishid.openinv.internal.common.container.slot.SlotPlaceholder;
|
||||
import com.lishid.openinv.internal.common.container.slot.SlotViewOnly;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minecraft.network.HashedStack;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ChestMenu;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.ContainerListener;
|
||||
import net.minecraft.world.inventory.ContainerSynchronizer;
|
||||
import net.minecraft.world.inventory.DataSlot;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.inventory.RemoteSlot;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* An extension of {@link AbstractContainerMenu} that supports {@link SlotPlaceholder placeholders}.
|
||||
*/
|
||||
@SuppressWarnings("HidingField") // Revisit when removing 1.21.4 support
|
||||
public abstract class OpenChestMenu<T extends Container & ISpecialInventory & InternalOwned<ServerPlayer>>
|
||||
extends AbstractContainerMenu {
|
||||
|
||||
protected static final int BOTTOM_INVENTORY_SIZE = 36;
|
||||
|
||||
protected final T container;
|
||||
protected final ServerPlayer viewer;
|
||||
protected final boolean viewOnly;
|
||||
protected final boolean ownContainer;
|
||||
protected final int topSize;
|
||||
private CraftInventoryView<OpenChestMenu<T>, Inventory> bukkitEntity;
|
||||
// Syncher fields
|
||||
protected @Nullable ContainerSynchronizer synchronizer;
|
||||
protected final List<DataSlot> dataSlots = new ArrayList<>();
|
||||
protected final IntList remoteDataSlots = new IntArrayList();
|
||||
protected final List<ContainerListener> containerListeners = new ArrayList<>();
|
||||
private RemoteSlot remoteCarried = RemoteSlot.PLACEHOLDER;
|
||||
protected boolean suppressRemoteUpdates;
|
||||
|
||||
protected OpenChestMenu(
|
||||
@NotNull MenuType<ChestMenu> type,
|
||||
int containerCounter,
|
||||
@NotNull T container,
|
||||
@NotNull ServerPlayer viewer,
|
||||
boolean viewOnly
|
||||
) {
|
||||
super(type, containerCounter);
|
||||
this.container = container;
|
||||
this.viewer = viewer;
|
||||
this.viewOnly = viewOnly;
|
||||
ownContainer = container.getOwnerHandle().equals(viewer);
|
||||
topSize = getTopSize(viewer);
|
||||
|
||||
preSlotSetup();
|
||||
|
||||
int upperRows = topSize / 9;
|
||||
// View's upper inventory - our container
|
||||
for (int row = 0; row < upperRows; ++row) {
|
||||
for (int col = 0; col < 9; ++col) {
|
||||
// x and y for client purposes, but hey, we're thorough here.
|
||||
// Adapted from net.minecraft.world.inventory.ChestMenu
|
||||
int x = 8 + col * 18;
|
||||
int y = 18 + row * 18;
|
||||
int index = row * 9 + col;
|
||||
|
||||
// Guard against weird inventory sizes.
|
||||
if (index >= container.getContainerSize()) {
|
||||
addSlot(new SlotViewOnly(container, index, x, y));
|
||||
continue;
|
||||
}
|
||||
|
||||
Slot slot = getUpperSlot(index, x, y);
|
||||
|
||||
addSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
// View's lower inventory - viewer inventory
|
||||
int playerInvPad = (upperRows - 4) * 18;
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 9; ++col) {
|
||||
int x = 8 + col * 18;
|
||||
int y = playerInvPad + row * 18 + 103;
|
||||
addSlot(new Slot(viewer.getInventory(), row * 9 + col + 9, x, y));
|
||||
}
|
||||
}
|
||||
// Hotbar
|
||||
for (int col = 0; col < 9; ++col) {
|
||||
int x = 8 + col * 18;
|
||||
int y = playerInvPad + 161;
|
||||
addSlot(new Slot(viewer.getInventory(), col, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull MenuType<ChestMenu> getChestMenuType(int inventorySize) {
|
||||
inventorySize = ((int) Math.ceil(inventorySize / 9.0)) * 9;
|
||||
return switch (inventorySize) {
|
||||
case 9 -> MenuType.GENERIC_9x1;
|
||||
case 18 -> MenuType.GENERIC_9x2;
|
||||
case 27 -> MenuType.GENERIC_9x3;
|
||||
case 36 -> MenuType.GENERIC_9x4;
|
||||
case 45 -> MenuType.GENERIC_9x5;
|
||||
case 54 -> MenuType.GENERIC_9x6;
|
||||
default -> throw new IllegalArgumentException("Inventory size unsupported: " + inventorySize);
|
||||
};
|
||||
}
|
||||
|
||||
protected void preSlotSetup() {
|
||||
}
|
||||
|
||||
protected @NotNull Slot getUpperSlot(int index, int x, int y) {
|
||||
Slot slot = new Slot(container, index, x, y);
|
||||
if (viewOnly) {
|
||||
return SlotViewOnly.wrap(slot);
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final @NotNull CraftInventoryView<OpenChestMenu<T>, Inventory> getBukkitView() {
|
||||
if (bukkitEntity == null) {
|
||||
bukkitEntity = createBukkitEntity();
|
||||
}
|
||||
|
||||
return bukkitEntity;
|
||||
}
|
||||
|
||||
protected @NotNull CraftInventoryView<OpenChestMenu<T>, Inventory> createBukkitEntity() {
|
||||
Inventory top;
|
||||
if (viewOnly) {
|
||||
top = new OpenDummyInventory(container, container.getBukkitType());
|
||||
} else {
|
||||
top = container.getBukkitInventory();
|
||||
}
|
||||
return new CraftInventoryView<>(viewer.getBukkitEntity(), top, this) {
|
||||
@Override
|
||||
public @Nullable Inventory getInventory(int rawSlot) {
|
||||
if (viewOnly) {
|
||||
return null;
|
||||
}
|
||||
return super.getInventory(rawSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertSlot(int rawSlot) {
|
||||
if (viewOnly) {
|
||||
return InventoryView.OUTSIDE;
|
||||
}
|
||||
return super.convertSlot(rawSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType.SlotType getSlotType(int slot) {
|
||||
if (viewOnly) {
|
||||
return InventoryType.SlotType.OUTSIDE;
|
||||
}
|
||||
return super.getSlotType(slot);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private int getTopSize(ServerPlayer viewer) {
|
||||
MenuType<?> menuType = getType();
|
||||
if (menuType == MenuType.GENERIC_9x1) {
|
||||
return 9;
|
||||
} else if (menuType == MenuType.GENERIC_9x2) {
|
||||
return 18;
|
||||
} else if (menuType == MenuType.GENERIC_9x3) {
|
||||
return 27;
|
||||
} else if (menuType == MenuType.GENERIC_9x4) {
|
||||
return 36;
|
||||
} else if (menuType == MenuType.GENERIC_9x5) {
|
||||
return 45;
|
||||
} else if (menuType == MenuType.GENERIC_9x6) {
|
||||
return 54;
|
||||
}
|
||||
// This is a bit gross, but allows us a safe fallthrough.
|
||||
return menuType.create(-1, viewer.getInventory()).slots.size() - BOTTOM_INVENTORY_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reimplementation of {@link AbstractContainerMenu#moveItemStackTo(ItemStack, int, int, boolean)} that ignores fake
|
||||
* slots and respects {@link Slot#hasItem()}.
|
||||
*
|
||||
* @param itemStack the stack to quick-move
|
||||
* @param rangeLow the start of the range of slots that can be moved to, inclusive
|
||||
* @param rangeHigh the end of the range of slots that can be moved to, exclusive
|
||||
* @param topDown whether to start at the top of the range or bottom
|
||||
* @return whether the stack was modified as a result of being quick-moved
|
||||
*/
|
||||
@Override
|
||||
protected boolean moveItemStackTo(ItemStack itemStack, int rangeLow, int rangeHigh, boolean topDown) {
|
||||
boolean modified = false;
|
||||
boolean stackable = itemStack.isStackable();
|
||||
Slot firstEmpty = null;
|
||||
|
||||
for (int index = topDown ? rangeHigh - 1 : rangeLow;
|
||||
!itemStack.isEmpty() && (topDown ? index >= rangeLow : index < rangeHigh);
|
||||
index += topDown ? -1 : 1
|
||||
) {
|
||||
Slot slot = slots.get(index);
|
||||
// If the slot cannot be added to, check the next slot.
|
||||
if (slot.isFake() || !slot.mayPlace(itemStack)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (slot.hasItem()) {
|
||||
// If the item isn't stackable, check the next slot.
|
||||
if (!stackable) {
|
||||
continue;
|
||||
}
|
||||
// Otherwise, add as many as we can from our stack to the slot.
|
||||
modified |= addToExistingStack(itemStack, slot);
|
||||
} else {
|
||||
// If this is the first empty slot, keep track of it for later use.
|
||||
if (firstEmpty == null) {
|
||||
firstEmpty = slot;
|
||||
}
|
||||
// If the item isn't stackable, we've located the slot we're adding it to, so we're done.
|
||||
if (!stackable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the item hasn't been fully added yet, add as many as we can to the first open slot.
|
||||
if (!itemStack.isEmpty() && firstEmpty != null) {
|
||||
firstEmpty.setByPlayer(itemStack.split(Math.min(itemStack.getCount(), firstEmpty.getMaxStackSize(itemStack))));
|
||||
firstEmpty.setChanged();
|
||||
modified = true;
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
private static boolean addToExistingStack(ItemStack itemStack, Slot slot) {
|
||||
ItemStack existing = slot.getItem();
|
||||
|
||||
// If the items aren't the same, we can't add our item.
|
||||
if (!ItemStack.isSameItemSameComponents(itemStack, existing)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int max = slot.getMaxStackSize(existing);
|
||||
int existingCount = existing.getCount();
|
||||
|
||||
// If the stack is already full, we can't add more.
|
||||
if (existingCount >= max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int total = existingCount + itemStack.getCount();
|
||||
|
||||
// If the existing item can accept the entirety of our item, we're done!
|
||||
if (total <= max) {
|
||||
itemStack.setCount(0);
|
||||
existing.setCount(total);
|
||||
slot.setChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, add as many as we can.
|
||||
itemStack.shrink(max - existingCount);
|
||||
existing.setCount(max);
|
||||
slot.setChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clicked(int i, int j, @NotNull ClickType clickType, @NotNull Player player) {
|
||||
if (viewOnly) {
|
||||
if (clickType == ClickType.QUICK_CRAFT) {
|
||||
sendAllDataToRemote();
|
||||
}
|
||||
return;
|
||||
}
|
||||
super.clicked(i, j, clickType, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overrides from here on are purely to modify the sync process to send placeholder items.
|
||||
@Override
|
||||
protected @NotNull Slot addSlot(@NotNull Slot slot) {
|
||||
slot.index = this.slots.size();
|
||||
this.slots.add(slot);
|
||||
this.lastSlots.add(ItemStack.EMPTY);
|
||||
this.remoteSlots.add(this.synchronizer != null ? this.synchronizer.createSlot() : RemoteSlot.PLACEHOLDER);
|
||||
return slot;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull DataSlot addDataSlot(@NotNull DataSlot dataSlot) {
|
||||
this.dataSlots.add(dataSlot);
|
||||
this.remoteDataSlots.add(0);
|
||||
return dataSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addDataSlots(ContainerData containerData) {
|
||||
for (int i = 0; i < containerData.getCount(); i++) {
|
||||
this.addDataSlot(DataSlot.forContainer(containerData, i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSlotListener(@NotNull ContainerListener containerListener) {
|
||||
if (!this.containerListeners.contains(containerListener)) {
|
||||
this.containerListeners.add(containerListener);
|
||||
this.broadcastChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSynchronizer(@NotNull ContainerSynchronizer containerSynchronizer) {
|
||||
this.synchronizer = containerSynchronizer;
|
||||
this.remoteCarried = synchronizer.createSlot();
|
||||
this.remoteSlots.replaceAll(slot -> synchronizer.createSlot());
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAllDataToRemote() {
|
||||
List<ItemStack> contentsCopy = new ArrayList<>();
|
||||
for (int index = 0; index < slots.size(); ++index) {
|
||||
Slot slot = slots.get(index);
|
||||
ItemStack itemStack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem();
|
||||
contentsCopy.add(itemStack);
|
||||
this.remoteSlots.get(index).force(itemStack);
|
||||
}
|
||||
|
||||
remoteCarried.force(getCarried());
|
||||
|
||||
for (int index = 0; index < this.dataSlots.size(); ++index) {
|
||||
this.remoteDataSlots.set(index, this.dataSlots.get(index).get());
|
||||
}
|
||||
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendInitialData(this, contentsCopy, this.getCarried().copy(), this.remoteDataSlots.toIntArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastCarriedItem() {
|
||||
ItemStack carried = this.getCarried();
|
||||
this.remoteCarried.force(carried);
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendCarriedChange(this, carried.copy());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSlotListener(@NotNull ContainerListener containerListener) {
|
||||
this.containerListeners.remove(containerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastChanges() {
|
||||
for (int index = 0; index < this.slots.size(); ++index) {
|
||||
Slot slot = this.slots.get(index);
|
||||
ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem();
|
||||
Supplier<ItemStack> supplier = Suppliers.memoize(itemstack::copy);
|
||||
this.triggerSlotListeners(index, itemstack, supplier);
|
||||
this.synchronizeSlotToRemote(index, itemstack, supplier);
|
||||
}
|
||||
|
||||
this.synchronizeCarriedToRemote();
|
||||
|
||||
for (int index = 0; index < this.dataSlots.size(); ++index) {
|
||||
DataSlot dataSlot = this.dataSlots.get(index);
|
||||
int j = dataSlot.get();
|
||||
if (dataSlot.checkAndClearUpdateFlag()) {
|
||||
this.updateDataSlotListeners(index, j);
|
||||
}
|
||||
|
||||
this.synchronizeDataSlotToRemote(index, j);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastFullState() {
|
||||
for (int index = 0; index < this.slots.size(); ++index) {
|
||||
ItemStack itemstack = this.slots.get(index).getItem();
|
||||
this.triggerSlotListeners(index, itemstack, itemstack::copy);
|
||||
}
|
||||
|
||||
for (int index = 0; index < this.dataSlots.size(); ++index) {
|
||||
DataSlot containerproperty = this.dataSlots.get(index);
|
||||
if (containerproperty.checkAndClearUpdateFlag()) {
|
||||
this.updateDataSlotListeners(index, containerproperty.get());
|
||||
}
|
||||
}
|
||||
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
private void updateDataSlotListeners(int i, int j) {
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.dataChanged(this, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerSlotListeners(int index, ItemStack itemStack, Supplier<ItemStack> supplier) {
|
||||
ItemStack itemStack1 = this.lastSlots.get(index);
|
||||
if (!ItemStack.matches(itemStack1, itemStack)) {
|
||||
ItemStack itemStack2 = supplier.get();
|
||||
this.lastSlots.set(index, itemStack2);
|
||||
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.slotChanged(this, index, itemStack2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeSlotToRemote(int i, ItemStack itemStack, Supplier<ItemStack> supplier) {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
RemoteSlot slot = this.remoteSlots.get(i);
|
||||
if (!slot.matches(itemStack)) {
|
||||
slot.force(itemStack);
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendSlotChange(this, i, supplier.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeDataSlotToRemote(int index, int value) {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
int existing = this.remoteDataSlots.getInt(index);
|
||||
if (existing != value) {
|
||||
this.remoteDataSlots.set(index, value);
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendDataChange(this, index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeCarriedToRemote() {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
ItemStack carried = this.getCarried();
|
||||
if (!this.remoteCarried.matches(carried)) {
|
||||
this.remoteCarried.force(carried);
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendCarriedChange(this, carried.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoteCarried(@NotNull HashedStack stack) {
|
||||
this.remoteCarried.receive(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suppressRemoteUpdates() {
|
||||
this.suppressRemoteUpdates = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeRemoteUpdates() {
|
||||
this.suppressRemoteUpdates = false;
|
||||
}
|
||||
|
||||
}
|
||||
-151
@@ -1,151 +0,0 @@
|
||||
package com.lishid.openinv.internal.common.container.slot;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A view-only {@link Slot}. "Blank" by default, but can wrap another slot to display its content.
|
||||
*/
|
||||
public class SlotViewOnly extends SlotPlaceholder {
|
||||
|
||||
public static @NotNull SlotViewOnly wrap(@NotNull Slot wrapped) {
|
||||
SlotViewOnly wrapper;
|
||||
if (wrapped instanceof SlotPlaceholder placeholder) {
|
||||
wrapper = new SlotViewOnly(wrapped.container, wrapped.slot, wrapped.x, wrapped.y) {
|
||||
@Override
|
||||
public ItemStack getOrDefault() {
|
||||
return placeholder.getOrDefault();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
wrapper = new SlotViewOnly(wrapped.container, wrapped.slot, wrapped.x, wrapped.y) {
|
||||
@Override
|
||||
public ItemStack getOrDefault() {
|
||||
return wrapped.getItem();
|
||||
}
|
||||
};
|
||||
}
|
||||
wrapper.index = wrapped.index;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
public SlotViewOnly(Container container, int index, int x, int y) {
|
||||
super(container, index, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOrDefault() {
|
||||
return Placeholders.notSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickCraft(@NotNull ItemStack itemStack1, @NotNull ItemStack itemStack2) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTake(@NotNull Player player, @NotNull ItemStack itemStack) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(@NotNull ItemStack itemStack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getItem() {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasItem() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByPlayer(@NotNull ItemStack newStack) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByPlayer(@NotNull ItemStack newStack, @NotNull ItemStack oldStack) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(@NotNull ItemStack itemStack) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChanged() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize(@NotNull ItemStack itemStack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack remove(int amount) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPickup(@NotNull Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<ItemStack> tryRemove(int var0, int var1, @NotNull Player player) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack safeTake(int var0, int var1, @NotNull Player player) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack safeInsert(@NotNull ItemStack itemStack) {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack safeInsert(@NotNull ItemStack itemStack, int amount) {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowModification(@NotNull Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHighlightable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFake() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
package com.lishid.openinv.internal.common.container.slot.placeholder;
|
||||
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.TagParser;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.CustomModelData;
|
||||
import net.minecraft.world.item.component.DyedItemColor;
|
||||
import net.minecraft.world.item.component.TooltipDisplay;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class PlaceholderLoader extends PlaceholderLoaderBase {
|
||||
|
||||
private static final CustomModelData DEFAULT_CUSTOM_MODEL_DATA = new CustomModelData(List.of(), List.of(), List.of("openinv:custom"), List.of());
|
||||
private static final TooltipDisplay HIDE_TOOLTIP = new TooltipDisplay(true, new LinkedHashSet<>());
|
||||
|
||||
@Override
|
||||
protected @NotNull CompoundTag parseTag(@NotNull String itemText) throws Exception {
|
||||
return TagParser.parseCompoundFully(itemText);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addModelData(@NotNull ItemStack itemStack) {
|
||||
itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void hideTooltip(@NotNull ItemStack itemStack) {
|
||||
itemStack.set(DataComponents.TOOLTIP_DISPLAY, HIDE_TOOLTIP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DyedItemColor getDye(int rgb) {
|
||||
return new DyedItemColor(rgb);
|
||||
}
|
||||
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
package com.lishid.openinv.internal.common.container.slot.placeholder;
|
||||
|
||||
import com.lishid.openinv.internal.common.player.BaseOpenPlayer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
public final class Placeholders {
|
||||
|
||||
static final @NotNull EnumMap<GameType, ItemStack> BLOCKED_GAME_TYPE = new EnumMap<>(GameType.class);
|
||||
public static @NotNull ItemStack craftingOutput = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack cursor = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack drop = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack emptyHelmet = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack emptyChestplate = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack emptyLeggings = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack emptyBoots = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack emptyOffHand = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack notSlot = ItemStack.EMPTY;
|
||||
public static @NotNull ItemStack blockedOffline = ItemStack.EMPTY;
|
||||
|
||||
public static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) {
|
||||
if (!BaseOpenPlayer.isConnected(serverPlayer.connection)) {
|
||||
return blockedOffline;
|
||||
}
|
||||
|
||||
return BLOCKED_GAME_TYPE.getOrDefault(serverPlayer.gameMode.getGameModeForPlayer(), ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
private Placeholders() {
|
||||
throw new IllegalStateException("Cannot create instance of utility class.");
|
||||
}
|
||||
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
package com.lishid.openinv.internal.common.player;
|
||||
|
||||
import com.lishid.openinv.event.OpenEvents;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.ProblemReporter;
|
||||
import net.minecraft.world.level.storage.PlayerDataStorage;
|
||||
import net.minecraft.world.level.storage.TagValueOutput;
|
||||
import net.minecraft.world.level.storage.ValueOutput;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class OpenPlayer extends BaseOpenPlayer {
|
||||
|
||||
protected OpenPlayer(
|
||||
CraftServer server,
|
||||
ServerPlayer entity,
|
||||
PlayerManager manager
|
||||
) {
|
||||
super(server, entity, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
if (OpenEvents.saveCancelled(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerPlayer player = this.getHandle();
|
||||
Logger logger = LogUtils.getLogger();
|
||||
// See net.minecraft.world.level.storage.PlayerDataStorage#save(EntityHuman)
|
||||
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), logger)) {
|
||||
PlayerDataStorage worldNBTStorage = server.getServer().getPlayerList().playerIo;
|
||||
|
||||
CompoundTag oldData = isOnline()
|
||||
? null
|
||||
: worldNBTStorage.load(player.getName().getString(), player.getStringUUID(), scopedCollector).orElse(null);
|
||||
CompoundTag playerData = getWritableTag(oldData);
|
||||
|
||||
ValueOutput valueOutput = TagValueOutput.createWrappingWithContext(scopedCollector, player.registryAccess(), playerData);
|
||||
player.saveWithoutId(valueOutput);
|
||||
|
||||
if (oldData != null) {
|
||||
// Revert certain special data values when offline.
|
||||
revertSpecialValues(playerData, oldData);
|
||||
}
|
||||
|
||||
Path playerDataDir = worldNBTStorage.getPlayerDir().toPath();
|
||||
Path tempFile = Files.createTempFile(playerDataDir, player.getStringUUID() + "-", ".dat");
|
||||
NbtIo.writeCompressed(playerData, tempFile);
|
||||
Path dataFile = playerDataDir.resolve(player.getStringUUID() + ".dat");
|
||||
Path backupFile = playerDataDir.resolve(player.getStringUUID() + ".dat_old");
|
||||
Util.safeReplaceFile(dataFile, tempFile, backupFile);
|
||||
} catch (Exception e) {
|
||||
LogUtils.getLogger().warn("Failed to save player data for {}: {}", player.getScoreboardName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") {
|
||||
val paper = candidates.firstOrNull {
|
||||
it.id.let { id ->
|
||||
id is ModuleComponentIdentifier && id.module == "paper-api"
|
||||
}
|
||||
}
|
||||
if (paper != null) {
|
||||
select(paper)
|
||||
}
|
||||
because("module is written for Paper servers")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi"))
|
||||
implementation(project(":openinvcommon"))
|
||||
implementation(project(":openinvadaptercommon"))
|
||||
implementation(project(":openinvadapterpaper1_21_5"))
|
||||
implementation(project(":openinvadapterpaper1_21_4"))
|
||||
implementation(project(":openinvadapterpaper1_21_3"))
|
||||
|
||||
paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT")
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_1;
|
||||
|
||||
import com.lishid.openinv.internal.Accessor;
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.internal.common.container.AnySilentContainer;
|
||||
import com.lishid.openinv.internal.paper1_21_1.container.OpenInventory;
|
||||
import com.lishid.openinv.internal.paper1_21_1.container.slot.placeholder.PlaceholderLoader;
|
||||
import com.lishid.openinv.internal.paper1_21_1.player.PlayerManager;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.OpenEnderChest;
|
||||
import com.lishid.openinv.util.lang.LanguageManager;
|
||||
import net.minecraft.world.Container;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class InternalAccessor implements Accessor {
|
||||
|
||||
private final @NotNull Logger logger;
|
||||
private final @NotNull PlayerManager manager;
|
||||
private final @NotNull AnySilentContainer anySilentContainer;
|
||||
|
||||
public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) {
|
||||
this.logger = logger;
|
||||
this.manager = new PlayerManager(logger);
|
||||
this.anySilentContainer = new AnySilentContainer(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerManager getPlayerManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IAnySilentContainer getAnySilentContainer() {
|
||||
return anySilentContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) {
|
||||
return new OpenInventory(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) {
|
||||
return new OpenEnderChest(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ISpecialInventory> @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class<T> clazz) {
|
||||
if (!(bukkitInventory instanceof CraftInventory craftInventory)) {
|
||||
return null;
|
||||
}
|
||||
Container container = craftInventory.getInventory();
|
||||
if (clazz.isInstance(container)) {
|
||||
return clazz.cast(container);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(@NotNull ConfigurationSection config) {
|
||||
ConfigurationSection placeholders = config.getConfigurationSection("placeholders");
|
||||
try {
|
||||
// Reset placeholders to defaults and try to load configuration.
|
||||
new PlaceholderLoader().load(placeholders);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_1.container;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.slot.Content;
|
||||
import com.lishid.openinv.internal.paper1_21_1.container.slot.ContentCraftingResult;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenInventory extends com.lishid.openinv.internal.paper1_21_4.container.OpenInventory {
|
||||
|
||||
public OpenInventory(@NotNull Player bukkitPlayer) {
|
||||
super(bukkitPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Content getCraftingResult(@NotNull ServerPlayer serverPlayer) {
|
||||
return new ContentCraftingResult(serverPlayer);
|
||||
}
|
||||
|
||||
}
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_1.container.slot.placeholder;
|
||||
|
||||
import com.lishid.openinv.internal.paper1_21_3.container.slot.placeholder.NumericDataPlaceholderLoader;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.entity.BannerPattern;
|
||||
import net.minecraft.world.level.block.entity.BannerPatternLayers;
|
||||
import net.minecraft.world.level.block.entity.BannerPatterns;
|
||||
import org.bukkit.craftbukkit.CraftRegistry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlaceholderLoader extends NumericDataPlaceholderLoader {
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack defaultCursor() {
|
||||
// Cursor-like banner with no tooltip
|
||||
ItemStack itemStack = new ItemStack(Items.WHITE_BANNER);
|
||||
RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry();
|
||||
Registry<BannerPattern> bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN);
|
||||
BannerPattern halfDiagBottomRight = bannerPatterns.getOrThrow(BannerPatterns.DIAGONAL_RIGHT);
|
||||
BannerPattern downRight = bannerPatterns.getOrThrow(BannerPatterns.STRIPE_DOWNRIGHT);
|
||||
BannerPattern border = bannerPatterns.getOrThrow(BannerPatterns.BORDER);
|
||||
itemStack.set(
|
||||
DataComponents.BANNER_PATTERNS,
|
||||
new BannerPatternLayers(
|
||||
List.of(
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfDiagBottomRight), DyeColor.GRAY),
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(downRight), DyeColor.WHITE),
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(border), DyeColor.GRAY)
|
||||
)
|
||||
)
|
||||
);
|
||||
addModelData(itemStack);
|
||||
itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack defaultShield() {
|
||||
// Shield with "missing texture" pattern, magenta and black squares.
|
||||
ItemStack itemStack = new ItemStack(Items.SHIELD);
|
||||
itemStack.set(DataComponents.BASE_COLOR, DyeColor.MAGENTA);
|
||||
RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry();
|
||||
Registry<BannerPattern> bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN);
|
||||
BannerPattern halfLeft = bannerPatterns.getOrThrow(BannerPatterns.HALF_VERTICAL);
|
||||
BannerPattern topLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_LEFT);
|
||||
BannerPattern topRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_RIGHT);
|
||||
BannerPattern bottomLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_LEFT);
|
||||
BannerPattern bottomRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_RIGHT);
|
||||
itemStack.set(DataComponents.BANNER_PATTERNS,
|
||||
new BannerPatternLayers(
|
||||
List.of(
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfLeft), DyeColor.BLACK),
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topLeft), DyeColor.MAGENTA),
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomLeft), DyeColor.MAGENTA),
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topRight), DyeColor.BLACK),
|
||||
new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomRight), DyeColor.BLACK)
|
||||
)
|
||||
)
|
||||
);
|
||||
itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE);
|
||||
addModelData(itemStack);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_1.player;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ClientInformation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.ChatVisiblity;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PlayerManager extends com.lishid.openinv.internal.paper1_21_4.player.PlayerManager {
|
||||
|
||||
public PlayerManager(@NotNull Logger logger) {
|
||||
super(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ServerPlayer createNewPlayer(
|
||||
@NotNull MinecraftServer server,
|
||||
@NotNull ServerLevel worldServer,
|
||||
@NotNull final OfflinePlayer offline
|
||||
) {
|
||||
// See net.minecraft.server.players.PlayerList#canPlayerLogin(ServerLoginPacketListenerImpl, GameProfile)
|
||||
// See net.minecraft.server.network.ServerLoginPacketListenerImpl#handleHello(ServerboundHelloPacket)
|
||||
GameProfile profile = new GameProfile(offline.getUniqueId(),
|
||||
offline.getName() != null ? offline.getName() : offline.getUniqueId().toString()
|
||||
);
|
||||
|
||||
ClientInformation dummyInfo = new ClientInformation(
|
||||
"en_us",
|
||||
1, // Reduce distance just in case.
|
||||
ChatVisiblity.HIDDEN, // Don't accept chat.
|
||||
false,
|
||||
ServerPlayer.DEFAULT_MODEL_CUSTOMIZATION,
|
||||
ServerPlayer.DEFAULT_MAIN_HAND,
|
||||
true,
|
||||
false // Don't list in player list (not that this player is in the list anyway).
|
||||
);
|
||||
|
||||
ServerPlayer entity = new ServerPlayer(server, worldServer, profile, dummyInfo);
|
||||
|
||||
try {
|
||||
injectPlayer(server, entity);
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(
|
||||
java.util.logging.Level.WARNING,
|
||||
e,
|
||||
() -> "Unable to inject ServerPlayer, certain player data may be lost when saving!"
|
||||
);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
plugins {
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.release = 21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi")) {
|
||||
exclude(group = "org.spigotmc", module = "spigot-api")
|
||||
}
|
||||
implementation(project(":openinvcommon")) {
|
||||
exclude(group = "org.spigotmc", module = "spigot-api")
|
||||
}
|
||||
implementation(project(":openinvadapterpaper26_1")) {
|
||||
exclude(group = "io.papermc.paper", module = "dev-bundle")
|
||||
}
|
||||
|
||||
paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT")
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.lishid.openinv.internal.paper1_21_11;
|
||||
|
||||
import com.github.jikoo.openinv.lang.LanguageManager;
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.internal.paper1_21_11.container.OpenEnderChest;
|
||||
import com.lishid.openinv.internal.paper1_21_11.container.OpenInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@NullMarked
|
||||
public class InternalAccessor extends com.lishid.openinv.internal.paper26_1.InternalAccessor {
|
||||
|
||||
public InternalAccessor(Logger logger, LanguageManager lang) {
|
||||
super(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISpecialEnderChest createEnderChest(Player player) {
|
||||
return new OpenEnderChest(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISpecialPlayerInventory createPlayerInventory(Player player) {
|
||||
return new OpenInventory(factory, player);
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.lishid.openinv.internal.paper1_21_11.container;
|
||||
|
||||
import com.github.jikoo.openinv.internal.container.slot.InventoryFactory;
|
||||
import com.lishid.openinv.internal.paper1_21_11.container.menu.OpenEnderChestMenu;
|
||||
import com.lishid.openinv.internal.paper26_3.container.menu.OpenChestMenu;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class OpenEnderChest extends com.lishid.openinv.internal.paper26_3.container.OpenEnderChest {
|
||||
|
||||
public OpenEnderChest(org.bukkit.entity.Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable OpenChestMenu<?> createMenu(
|
||||
InventoryFactory<ServerPlayer, ItemStack, Container, Slot, EquipmentSlot> factory,
|
||||
Player player,
|
||||
int i,
|
||||
boolean viewOnly
|
||||
) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
return new OpenEnderChestMenu(factory, this, serverPlayer, i, viewOnly);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.lishid.openinv.internal.paper1_21_11.container;
|
||||
|
||||
import com.github.jikoo.openinv.internal.container.slot.InventoryFactory;
|
||||
import com.lishid.openinv.internal.paper1_21_11.container.menu.OpenInventoryMenu;
|
||||
import com.lishid.openinv.internal.paper26_3.container.menu.OpenChestMenu;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class OpenInventory extends com.lishid.openinv.internal.paper26_3.container.OpenInventory {
|
||||
|
||||
public OpenInventory(
|
||||
InventoryFactory<ServerPlayer, ItemStack, Container, Slot, EquipmentSlot> factory,
|
||||
org.bukkit.entity.Player bukkitPlayer
|
||||
) {
|
||||
super(factory, bukkitPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable OpenChestMenu<?> createMenu(Player player, int i, boolean viewOnly) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
return new OpenInventoryMenu(factory, this, serverPlayer, i, viewOnly);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package com.lishid.openinv.internal.paper1_21_11.container.menu;
|
||||
|
||||
import com.github.jikoo.openinv.internal.container.slot.InventoryFactory;
|
||||
import com.lishid.openinv.internal.paper26_3.container.OpenEnderChest;
|
||||
import com.lishid.openinv.internal.paper26_3.container.menu.OpenSyncMenu;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class OpenEnderChestMenu extends OpenSyncMenu<OpenEnderChest> {
|
||||
|
||||
public OpenEnderChestMenu(
|
||||
InventoryFactory<ServerPlayer, ItemStack, Container, Slot, EquipmentSlot> factory,
|
||||
OpenEnderChest enderChest,
|
||||
ServerPlayer viewer,
|
||||
int containerId,
|
||||
boolean viewOnly
|
||||
) {
|
||||
super(getChestMenuType(enderChest.getContainerSize()), containerId, factory, enderChest, viewer, viewOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack quickMoveStack(Player player, int index) {
|
||||
if (viewOnly) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
// See ChestMenu
|
||||
Slot slot = this.slots.get(index);
|
||||
|
||||
if (slot.isFake() || !slot.hasItem()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack itemStack = slot.getItem();
|
||||
ItemStack original = itemStack.copy();
|
||||
|
||||
if (index < topSize) {
|
||||
if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.moveItemStackTo(itemStack, 0, topSize, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (itemStack.isEmpty()) {
|
||||
slot.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.setChanged();
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clicked(int i, int j, ClickType clickType, Player player) {
|
||||
if (viewOnly) {
|
||||
if (clickType == ClickType.QUICK_CRAFT) {
|
||||
sendAllDataToRemote();
|
||||
}
|
||||
return;
|
||||
}
|
||||
super.clicked(i, j, clickType, player);
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.lishid.openinv.internal.paper1_21_11.container.menu;
|
||||
|
||||
import com.github.jikoo.openinv.internal.container.slot.InventoryFactory;
|
||||
import com.lishid.openinv.internal.paper26_3.container.BaseOpenInventory;
|
||||
import com.lishid.openinv.internal.paper26_3.container.menu.BaseOpenInventoryMenu;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
public class OpenInventoryMenu extends BaseOpenInventoryMenu {
|
||||
|
||||
public OpenInventoryMenu(
|
||||
InventoryFactory<ServerPlayer, ItemStack, Container, Slot, EquipmentSlot> factory,
|
||||
BaseOpenInventory inventory,
|
||||
ServerPlayer viewer,
|
||||
int i,
|
||||
boolean viewOnly
|
||||
) {
|
||||
super(factory, inventory, viewer, i, viewOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clicked(int i, int j, ClickType clickType, Player player) {
|
||||
if (viewOnly) {
|
||||
if (clickType == ClickType.QUICK_CRAFT) {
|
||||
sendAllDataToRemote();
|
||||
}
|
||||
return;
|
||||
}
|
||||
super.clicked(i, j, clickType, player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") {
|
||||
val paper = candidates.firstOrNull {
|
||||
it.id.let { id ->
|
||||
id is ModuleComponentIdentifier && id.module == "paper-api"
|
||||
}
|
||||
}
|
||||
if (paper != null) {
|
||||
select(paper)
|
||||
}
|
||||
because("module is written for Paper servers")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi"))
|
||||
implementation(project(":openinvcommon"))
|
||||
implementation(project(":openinvadaptercommon"))
|
||||
implementation(project(":openinvadapterpaper1_21_5"))
|
||||
implementation(project(":openinvadapterpaper1_21_4"))
|
||||
|
||||
paperweight.paperDevBundle("1.21.3-R0.1-SNAPSHOT")
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_3;
|
||||
|
||||
import com.lishid.openinv.internal.paper1_21_3.container.slot.placeholder.NumericDataPlaceholderLoader;
|
||||
import com.lishid.openinv.util.lang.LanguageManager;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class InternalAccessor extends com.lishid.openinv.internal.paper1_21_4.InternalAccessor {
|
||||
|
||||
public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) {
|
||||
super(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(@NotNull ConfigurationSection config) {
|
||||
ConfigurationSection placeholders = config.getConfigurationSection("placeholders");
|
||||
try {
|
||||
// Reset placeholders to defaults and try to load configuration.
|
||||
new NumericDataPlaceholderLoader().load(placeholders);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_3.container.slot.placeholder;
|
||||
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder.CustomModelBase;
|
||||
import net.minecraft.world.item.component.CustomModelData;
|
||||
|
||||
public class NumericDataPlaceholderLoader extends CustomModelBase {
|
||||
|
||||
public NumericDataPlaceholderLoader() {
|
||||
super(new CustomModelData(9999));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") {
|
||||
val paper = candidates.firstOrNull {
|
||||
it.id.let { id ->
|
||||
id is ModuleComponentIdentifier && id.module == "paper-api"
|
||||
}
|
||||
}
|
||||
if (paper != null) {
|
||||
select(paper)
|
||||
}
|
||||
because("module is written for Paper servers")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi"))
|
||||
implementation(project(":openinvcommon"))
|
||||
implementation(project(":openinvadaptercommon"))
|
||||
implementation(project(":openinvadapterpaper1_21_5"))
|
||||
|
||||
paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT")
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4;
|
||||
|
||||
import com.lishid.openinv.internal.Accessor;
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.internal.common.container.AnySilentContainer;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.OpenEnderChest;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder.CustomModelPlaceholderLoader;
|
||||
import com.lishid.openinv.internal.paper1_21_4.player.PlayerManager;
|
||||
import com.lishid.openinv.util.lang.LanguageManager;
|
||||
import net.minecraft.world.Container;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class InternalAccessor implements Accessor {
|
||||
|
||||
protected final @NotNull Logger logger;
|
||||
private final @NotNull PlayerManager manager;
|
||||
private final @NotNull AnySilentContainer anySilentContainer;
|
||||
|
||||
public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) {
|
||||
this.logger = logger;
|
||||
manager = new PlayerManager(logger);
|
||||
anySilentContainer = new AnySilentContainer(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerManager getPlayerManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IAnySilentContainer getAnySilentContainer() {
|
||||
return anySilentContainer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ISpecialPlayerInventory createPlayerInventory(@NotNull Player player) {
|
||||
return new OpenInventory(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) {
|
||||
return new OpenEnderChest(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ISpecialInventory> @Nullable T get(@NotNull Inventory bukkitInventory, @NotNull Class<T> clazz) {
|
||||
if (!(bukkitInventory instanceof CraftInventory craftInventory)) {
|
||||
return null;
|
||||
}
|
||||
Container container = craftInventory.getInventory();
|
||||
if (clazz.isInstance(container)) {
|
||||
return clazz.cast(container);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(@NotNull ConfigurationSection config) {
|
||||
ConfigurationSection placeholders = config.getConfigurationSection("placeholders");
|
||||
try {
|
||||
// Reset placeholders to defaults and try to load configuration.
|
||||
new CustomModelPlaceholderLoader().load(placeholders);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container;
|
||||
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.menu.OpenEnderChestMenu;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OpenEnderChest extends com.lishid.openinv.internal.common.container.OpenEnderChest {
|
||||
|
||||
public OpenEnderChest(@NotNull Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(
|
||||
net.minecraft.world.entity.player.Player player,
|
||||
int i,
|
||||
boolean viewOnly
|
||||
) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
return new OpenEnderChestMenu(this, serverPlayer, i, viewOnly);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-191
@@ -1,191 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.slot.ContentCrafting;
|
||||
import com.lishid.openinv.internal.common.container.slot.ContentCursor;
|
||||
import com.lishid.openinv.internal.common.container.slot.ContentDrop;
|
||||
import com.lishid.openinv.internal.common.container.slot.ContentList;
|
||||
import com.lishid.openinv.internal.common.container.slot.ContentViewOnly;
|
||||
import com.lishid.openinv.internal.common.container.slot.SlotViewOnly;
|
||||
import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.bukkit.OpenPlayerInventory;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.menu.OpenInventoryMenu;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.slot.ContentEquipment;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.slot.ContentOffHand;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OpenInventory extends com.lishid.openinv.internal.common.container.OpenInventory {
|
||||
|
||||
public OpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) {
|
||||
super(bukkitPlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupSlots() {
|
||||
// Top of inventory: Regular contents.
|
||||
int nextIndex = addMainInventory();
|
||||
|
||||
// If inventory is expected size, we can arrange slots to be pretty.
|
||||
Inventory ownerInv = owner.getInventory();
|
||||
if (ownerInv.items.size() == 36
|
||||
&& ownerInv.armor.size() == 4
|
||||
&& ownerInv.offhand.size() == 1
|
||||
&& owner.inventoryMenu.getCraftSlots().getContainerSize() == 4) {
|
||||
// Armor slots: Bottom left.
|
||||
addArmor(36);
|
||||
// Off-hand: Below chestplate.
|
||||
addOffHand(46);
|
||||
// Drop slot: Bottom right.
|
||||
slots.set(53, new ContentDrop(owner));
|
||||
// Cursor slot: Above drop.
|
||||
slots.set(44, new ContentCursor(owner));
|
||||
|
||||
// Crafting is displayed in the bottom right corner.
|
||||
// As we're using the pretty view, this is a 3x2.
|
||||
addCrafting(41, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we'll just add elements linearly.
|
||||
nextIndex = addArmor(nextIndex);
|
||||
nextIndex = addOffHand(nextIndex);
|
||||
nextIndex = addCrafting(nextIndex, false);
|
||||
slots.set(nextIndex, new ContentCursor(owner));
|
||||
// Drop slot last.
|
||||
slots.set(slots.size() - 1, new ContentDrop(owner));
|
||||
}
|
||||
|
||||
private int addMainInventory() {
|
||||
int listSize = owner.getInventory().items.size();
|
||||
// Hotbar slots are 0-8. We want those to appear on the bottom of the inventory like a normal player inventory,
|
||||
// so everything else needs to move up a row.
|
||||
int hotbarDiff = listSize - 9;
|
||||
for (int localIndex = 0; localIndex < listSize; ++localIndex) {
|
||||
InventoryType.SlotType type;
|
||||
int invIndex;
|
||||
if (localIndex < hotbarDiff) {
|
||||
invIndex = localIndex + 9;
|
||||
type = InventoryType.SlotType.CONTAINER;
|
||||
} else {
|
||||
type = InventoryType.SlotType.QUICKBAR;
|
||||
invIndex = localIndex - hotbarDiff;
|
||||
}
|
||||
|
||||
slots.set(
|
||||
localIndex,
|
||||
new ContentList(owner, invIndex, type) {
|
||||
@Override
|
||||
public void setHolder(@NotNull ServerPlayer holder) {
|
||||
items = holder.getInventory().items;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return listSize;
|
||||
}
|
||||
|
||||
private int addArmor(int startIndex) {
|
||||
int listSize = owner.getInventory().armor.size();
|
||||
|
||||
for (int i = 0; i < listSize; ++i) {
|
||||
// Armor slots go bottom to top; boots are slot 0, helmet is slot 3.
|
||||
// Since we have to display horizontally due to space restrictions,
|
||||
// making the left side the "top" is more user-friendly.
|
||||
int armorIndex;
|
||||
EquipmentSlot slot;
|
||||
switch (i) {
|
||||
case 3 -> {
|
||||
armorIndex = 0;
|
||||
slot = EquipmentSlot.FEET;
|
||||
}
|
||||
case 2 -> {
|
||||
armorIndex = 1;
|
||||
slot = EquipmentSlot.LEGS;
|
||||
}
|
||||
case 1 -> {
|
||||
armorIndex = 2;
|
||||
slot = EquipmentSlot.CHEST;
|
||||
}
|
||||
case 0 -> {
|
||||
armorIndex = 3;
|
||||
slot = EquipmentSlot.HEAD;
|
||||
}
|
||||
default -> {
|
||||
// In the event that new armor slots are added, they can be placed at the end.
|
||||
armorIndex = i;
|
||||
slot = EquipmentSlot.MAINHAND;
|
||||
}
|
||||
}
|
||||
|
||||
slots.set(startIndex + i, new ContentEquipment(owner, armorIndex, slot));
|
||||
}
|
||||
|
||||
return startIndex + listSize;
|
||||
}
|
||||
|
||||
private int addOffHand(int startIndex) {
|
||||
int listSize = owner.getInventory().offhand.size();
|
||||
for (int localIndex = 0; localIndex < listSize; ++localIndex) {
|
||||
slots.set(startIndex + localIndex, new ContentOffHand(owner, localIndex));
|
||||
}
|
||||
return startIndex + listSize;
|
||||
}
|
||||
|
||||
private int addCrafting(int startIndex, boolean pretty) {
|
||||
int listSize = owner.inventoryMenu.getCraftSlots().getContents().size();
|
||||
pretty &= listSize == 4;
|
||||
|
||||
for (int localIndex = 0; localIndex < listSize; ++localIndex) {
|
||||
// Pretty display is a 2x2 rather than linear.
|
||||
// If index is in top row, grid is not 2x2, or pretty is disabled, just use current index.
|
||||
// Otherwise, subtract 2 and add 9 to start in the same position on the next row.
|
||||
int modIndex = startIndex + (localIndex < 2 || !pretty ? localIndex : localIndex + 7);
|
||||
|
||||
slots.set(modIndex, new ContentCrafting(owner, localIndex));
|
||||
}
|
||||
|
||||
if (pretty) {
|
||||
slots.set(startIndex + 2, new ContentViewOnly(owner) {
|
||||
@Override
|
||||
public Slot asSlot(Container container, int slot, int x, int y) {
|
||||
return new SlotViewOnly(container, slot, x, y) {
|
||||
@Override
|
||||
public ItemStack getOrDefault() {
|
||||
return Placeholders.craftingOutput;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
slots.set(startIndex + 11, getCraftingResult(owner));
|
||||
}
|
||||
|
||||
return startIndex + listSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() {
|
||||
if (bukkitEntity == null) {
|
||||
bukkitEntity = new OpenPlayerInventory(this);
|
||||
}
|
||||
return bukkitEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AbstractContainerMenu createMenu(Player player, int i, boolean viewOnly) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
return new OpenInventoryMenu(this, serverPlayer, i, viewOnly);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-225
@@ -1,225 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.bukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OpenPlayerInventory extends CraftInventory implements PlayerInventory {
|
||||
|
||||
public OpenPlayerInventory(@NotNull OpenInventory inventory) {
|
||||
super(inventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull OpenInventory getInventory() {
|
||||
return (OpenInventory) super.getInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack @NotNull [] getContents() {
|
||||
return asCraftMirror(getInventory().getOwnerHandle().getInventory().getContents());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContents(ItemStack[] items) {
|
||||
Inventory internal = getInventory().getOwnerHandle().getInventory();
|
||||
int size = internal.getContainerSize();
|
||||
Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size);
|
||||
|
||||
for (int index = 0; index < size; ++index) {
|
||||
if (index < items.length) {
|
||||
internal.setItem(index, CraftItemStack.asNMSCopy(items[index]));
|
||||
} else {
|
||||
internal.setItem(index, net.minecraft.world.item.ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack @NotNull [] getStorageContents() {
|
||||
return asCraftMirror(getInventory().getOwnerHandle().getInventory().items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageContents(ItemStack[] items) throws IllegalArgumentException {
|
||||
NonNullList<net.minecraft.world.item.ItemStack> list = getInventory().getOwnerHandle().getInventory().items;
|
||||
int size = list.size();
|
||||
Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size);
|
||||
for (int index = 0; index < items.length; ++index) {
|
||||
list.set(index, CraftItemStack.asNMSCopy(items[index]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType getType() {
|
||||
return InventoryType.PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player getHolder() {
|
||||
return getInventory().getOwner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack @NotNull [] getArmorContents() {
|
||||
return asCraftMirror(getInventory().getOwnerHandle().getInventory().armor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArmorContents(ItemStack @NotNull [] items) {
|
||||
NonNullList<net.minecraft.world.item.ItemStack> list = getInventory().getOwnerHandle().getInventory().armor;
|
||||
int size = list.size();
|
||||
Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size);
|
||||
for (int index = 0; index < items.length; ++index) {
|
||||
list.set(index, CraftItemStack.asNMSCopy(items[index]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack @NotNull [] getExtraContents() {
|
||||
return asCraftMirror(getInventory().getOwnerHandle().getInventory().offhand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtraContents(ItemStack @NotNull [] items) {
|
||||
NonNullList<net.minecraft.world.item.ItemStack> list = getInventory().getOwnerHandle().getInventory().offhand;
|
||||
int size = list.size();
|
||||
Preconditions.checkArgument(items.length <= size, "items.length must be <= %s", size);
|
||||
for (int index = 0; index < items.length; ++index) {
|
||||
list.set(index, CraftItemStack.asNMSCopy(items[index]));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getHelmet() {
|
||||
return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory()
|
||||
.getArmor(EquipmentSlot.HEAD.getIndex()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHelmet(@Nullable ItemStack helmet) {
|
||||
getInventory().getOwnerHandle().getInventory().armor
|
||||
.set(EquipmentSlot.HEAD.getIndex(), CraftItemStack.asNMSCopy(helmet));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getChestplate() {
|
||||
return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory()
|
||||
.getArmor(EquipmentSlot.CHEST.getIndex()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChestplate(@Nullable ItemStack chestplate) {
|
||||
getInventory().getOwnerHandle().getInventory().armor
|
||||
.set(EquipmentSlot.CHEST.getIndex(), CraftItemStack.asNMSCopy(chestplate));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getLeggings() {
|
||||
return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory()
|
||||
.getArmor(EquipmentSlot.LEGS.getIndex()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLeggings(@Nullable ItemStack leggings) {
|
||||
getInventory().getOwnerHandle().getInventory().armor
|
||||
.set(EquipmentSlot.LEGS.getIndex(), CraftItemStack.asNMSCopy(leggings));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getBoots() {
|
||||
return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory()
|
||||
.getArmor(EquipmentSlot.FEET.getIndex()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoots(@Nullable ItemStack boots) {
|
||||
getInventory().getOwnerHandle().getInventory().armor
|
||||
.set(EquipmentSlot.FEET.getIndex(), CraftItemStack.asNMSCopy(boots));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getItemInMainHand() {
|
||||
Inventory internal = getInventory().getOwnerHandle().getInventory();
|
||||
return CraftItemStack.asCraftMirror(internal.getItem(internal.selected));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInMainHand(@Nullable ItemStack item) {
|
||||
Inventory internal = getInventory().getOwnerHandle().getInventory();
|
||||
internal.setItem(internal.selected, CraftItemStack.asNMSCopy(item));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getItemInOffHand() {
|
||||
return CraftItemStack.asCraftMirror(getInventory().getOwnerHandle().getInventory().offhand.getFirst());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInOffHand(@Nullable ItemStack item) {
|
||||
getInventory().getOwnerHandle().getInventory().offhand.set(0, CraftItemStack.asNMSCopy(item));
|
||||
}
|
||||
|
||||
@SuppressWarnings("InlineMeSuggester")
|
||||
@Deprecated
|
||||
@Override
|
||||
public @NotNull ItemStack getItemInHand() {
|
||||
return getItemInMainHand();
|
||||
}
|
||||
|
||||
@SuppressWarnings("InlineMeSuggester")
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setItemInHand(@Nullable ItemStack stack) {
|
||||
setItemInMainHand(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeldItemSlot() {
|
||||
Inventory internal = getInventory().getOwnerHandle().getInventory();
|
||||
return internal.items.size() - 9 + internal.selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeldItemSlot(int slot) {
|
||||
slot %= 9;
|
||||
getInventory().getOwnerHandle().getInventory().selected = slot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack getItem(@NotNull org.bukkit.inventory.EquipmentSlot slot) {
|
||||
return switch (slot) {
|
||||
case HAND -> getItemInMainHand();
|
||||
case OFF_HAND -> getItemInOffHand();
|
||||
case FEET -> getBoots();
|
||||
case LEGS -> getLeggings();
|
||||
case CHEST -> getChestplate();
|
||||
case HEAD -> getHelmet();
|
||||
default -> throw new IllegalArgumentException("Unsupported EquipmentSlot " + slot);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(@NotNull org.bukkit.inventory.EquipmentSlot slot, @Nullable ItemStack item) {
|
||||
switch (slot) {
|
||||
case HAND -> setItemInMainHand(item);
|
||||
case OFF_HAND -> setItemInOffHand(item);
|
||||
case FEET -> setBoots(item);
|
||||
case LEGS -> setLeggings(item);
|
||||
case CHEST -> setChestplate(item);
|
||||
case HEAD -> setHelmet(item);
|
||||
default -> throw new IllegalArgumentException("Unsupported EquipmentSlot " + slot);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.bukkit;
|
||||
|
||||
import com.lishid.openinv.internal.paper1_21_4.container.OpenInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenPlayerInventorySelf extends OpenPlayerInventory {
|
||||
|
||||
private final int offset;
|
||||
|
||||
public OpenPlayerInventorySelf(@NotNull OpenInventory inventory, int offset) {
|
||||
super(inventory);
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int index) {
|
||||
return super.getItem(offset + index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int index, ItemStack item) {
|
||||
super.setItem(offset + index, item);
|
||||
}
|
||||
|
||||
}
|
||||
-467
@@ -1,467 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.menu;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.InternalOwned;
|
||||
import com.lishid.openinv.internal.common.container.bukkit.OpenDummyInventory;
|
||||
import com.lishid.openinv.internal.common.container.slot.SlotPlaceholder;
|
||||
import com.lishid.openinv.internal.common.container.slot.SlotViewOnly;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ChestMenu;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.ContainerListener;
|
||||
import net.minecraft.world.inventory.ContainerSynchronizer;
|
||||
import net.minecraft.world.inventory.DataSlot;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* An extension of {@link AbstractContainerMenu} that supports {@link SlotPlaceholder placeholders}.
|
||||
*/
|
||||
@SuppressWarnings("HidingField")
|
||||
public abstract class OpenChestMenu<T extends Container & ISpecialInventory & InternalOwned<ServerPlayer>>
|
||||
extends AbstractContainerMenu {
|
||||
|
||||
protected static final int BOTTOM_INVENTORY_SIZE = 36;
|
||||
|
||||
protected final T container;
|
||||
protected final ServerPlayer viewer;
|
||||
protected final boolean viewOnly;
|
||||
protected final boolean ownContainer;
|
||||
protected final int topSize;
|
||||
private CraftInventoryView<OpenChestMenu<T>, Inventory> bukkitEntity;
|
||||
// Syncher fields
|
||||
private @Nullable ContainerSynchronizer synchronizer;
|
||||
private final List<DataSlot> dataSlots = new ArrayList<>();
|
||||
private final IntList remoteDataSlots = new IntArrayList();
|
||||
private final List<ContainerListener> containerListeners = new ArrayList<>();
|
||||
private ItemStack remoteCarried = ItemStack.EMPTY;
|
||||
private boolean suppressRemoteUpdates;
|
||||
|
||||
protected OpenChestMenu(
|
||||
@NotNull MenuType<ChestMenu> type,
|
||||
int containerCounter,
|
||||
@NotNull T container,
|
||||
@NotNull ServerPlayer viewer,
|
||||
boolean viewOnly
|
||||
) {
|
||||
super(type, containerCounter);
|
||||
this.container = container;
|
||||
this.viewer = viewer;
|
||||
this.viewOnly = viewOnly;
|
||||
ownContainer = container.getOwnerHandle().equals(viewer);
|
||||
topSize = getTopSize(viewer);
|
||||
|
||||
preSlotSetup();
|
||||
|
||||
int upperRows = topSize / 9;
|
||||
// View's upper inventory - our container
|
||||
for (int row = 0; row < upperRows; ++row) {
|
||||
for (int col = 0; col < 9; ++col) {
|
||||
// x and y for client purposes, but hey, we're thorough here.
|
||||
// Adapted from net.minecraft.world.inventory.ChestMenu
|
||||
int x = 8 + col * 18;
|
||||
int y = 18 + row * 18;
|
||||
int index = row * 9 + col;
|
||||
|
||||
// Guard against weird inventory sizes.
|
||||
if (index >= container.getContainerSize()) {
|
||||
addSlot(new SlotViewOnly(container, index, x, y));
|
||||
continue;
|
||||
}
|
||||
|
||||
Slot slot = getUpperSlot(index, x, y);
|
||||
|
||||
addSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
// View's lower inventory - viewer inventory
|
||||
int playerInvPad = (upperRows - 4) * 18;
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 9; ++col) {
|
||||
int x = 8 + col * 18;
|
||||
int y = playerInvPad + row * 18 + 103;
|
||||
addSlot(new Slot(viewer.getInventory(), row * 9 + col + 9, x, y));
|
||||
}
|
||||
}
|
||||
// Hotbar
|
||||
for (int col = 0; col < 9; ++col) {
|
||||
int x = 8 + col * 18;
|
||||
int y = playerInvPad + 161;
|
||||
addSlot(new Slot(viewer.getInventory(), col, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
protected void preSlotSetup() {
|
||||
}
|
||||
|
||||
protected @NotNull Slot getUpperSlot(int index, int x, int y) {
|
||||
Slot slot = new Slot(container, index, x, y);
|
||||
if (viewOnly) {
|
||||
return SlotViewOnly.wrap(slot);
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final @NotNull CraftInventoryView<OpenChestMenu<T>, Inventory> getBukkitView() {
|
||||
if (bukkitEntity == null) {
|
||||
bukkitEntity = createBukkitEntity();
|
||||
}
|
||||
|
||||
return bukkitEntity;
|
||||
}
|
||||
|
||||
protected @NotNull CraftInventoryView<OpenChestMenu<T>, Inventory> createBukkitEntity() {
|
||||
Inventory top;
|
||||
if (viewOnly) {
|
||||
top = new OpenDummyInventory(container, container.getBukkitType());
|
||||
} else {
|
||||
top = container.getBukkitInventory();
|
||||
}
|
||||
return new CraftInventoryView<>(viewer.getBukkitEntity(), top, this) {
|
||||
@Override
|
||||
public @Nullable Inventory getInventory(int rawSlot) {
|
||||
if (viewOnly) {
|
||||
return null;
|
||||
}
|
||||
return super.getInventory(rawSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertSlot(int rawSlot) {
|
||||
if (viewOnly) {
|
||||
return InventoryView.OUTSIDE;
|
||||
}
|
||||
return super.convertSlot(rawSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType.SlotType getSlotType(int slot) {
|
||||
if (viewOnly) {
|
||||
return InventoryType.SlotType.OUTSIDE;
|
||||
}
|
||||
return super.getSlotType(slot);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private int getTopSize(ServerPlayer viewer) {
|
||||
MenuType<?> menuType = getType();
|
||||
if (menuType == MenuType.GENERIC_9x1) {
|
||||
return 9;
|
||||
} else if (menuType == MenuType.GENERIC_9x2) {
|
||||
return 18;
|
||||
} else if (menuType == MenuType.GENERIC_9x3) {
|
||||
return 27;
|
||||
} else if (menuType == MenuType.GENERIC_9x4) {
|
||||
return 36;
|
||||
} else if (menuType == MenuType.GENERIC_9x5) {
|
||||
return 45;
|
||||
} else if (menuType == MenuType.GENERIC_9x6) {
|
||||
return 54;
|
||||
}
|
||||
// This is a bit gross, but allows us a safe fallthrough.
|
||||
return menuType.create(-1, viewer.getInventory()).slots.size() - BOTTOM_INVENTORY_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reimplementation of {@link AbstractContainerMenu#moveItemStackTo(ItemStack, int, int, boolean)} that ignores fake
|
||||
* slots and respects {@link Slot#hasItem()}.
|
||||
*
|
||||
* @param itemStack the stack to quick-move
|
||||
* @param rangeLow the start of the range of slots that can be moved to, inclusive
|
||||
* @param rangeHigh the end of the range of slots that can be moved to, exclusive
|
||||
* @param topDown whether to start at the top of the range or bottom
|
||||
* @return whether the stack was modified as a result of being quick-moved
|
||||
*/
|
||||
@Override
|
||||
protected boolean moveItemStackTo(ItemStack itemStack, int rangeLow, int rangeHigh, boolean topDown) {
|
||||
boolean modified = false;
|
||||
boolean stackable = itemStack.isStackable();
|
||||
Slot firstEmpty = null;
|
||||
|
||||
for (int index = topDown ? rangeHigh - 1 : rangeLow;
|
||||
!itemStack.isEmpty() && (topDown ? index >= rangeLow : index < rangeHigh);
|
||||
index += topDown ? -1 : 1
|
||||
) {
|
||||
Slot slot = slots.get(index);
|
||||
// If the slot cannot be added to, check the next slot.
|
||||
if (slot.isFake() || !slot.mayPlace(itemStack)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (slot.hasItem()) {
|
||||
// If the item isn't stackable, check the next slot.
|
||||
if (!stackable) {
|
||||
continue;
|
||||
}
|
||||
// Otherwise, add as many as we can from our stack to the slot.
|
||||
modified |= addToExistingStack(itemStack, slot);
|
||||
} else {
|
||||
// If this is the first empty slot, keep track of it for later use.
|
||||
if (firstEmpty == null) {
|
||||
firstEmpty = slot;
|
||||
}
|
||||
// If the item isn't stackable, we've located the slot we're adding it to, so we're done.
|
||||
if (!stackable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the item hasn't been fully added yet, add as many as we can to the first open slot.
|
||||
if (!itemStack.isEmpty() && firstEmpty != null) {
|
||||
firstEmpty.setByPlayer(itemStack.split(Math.min(itemStack.getCount(), firstEmpty.getMaxStackSize(itemStack))));
|
||||
firstEmpty.setChanged();
|
||||
modified = true;
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
private static boolean addToExistingStack(ItemStack itemStack, Slot slot) {
|
||||
ItemStack existing = slot.getItem();
|
||||
|
||||
// If the items aren't the same, we can't add our item.
|
||||
if (!ItemStack.isSameItemSameComponents(itemStack, existing)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int max = slot.getMaxStackSize(existing);
|
||||
int existingCount = existing.getCount();
|
||||
|
||||
// If the stack is already full, we can't add more.
|
||||
if (existingCount >= max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int total = existingCount + itemStack.getCount();
|
||||
|
||||
// If the existing item can accept the entirety of our item, we're done!
|
||||
if (total <= max) {
|
||||
itemStack.setCount(0);
|
||||
existing.setCount(total);
|
||||
slot.setChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, add as many as we can.
|
||||
itemStack.shrink(max - existingCount);
|
||||
existing.setCount(max);
|
||||
slot.setChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clicked(int i, int j, @NotNull ClickType clickType, @NotNull Player player) {
|
||||
if (viewOnly) {
|
||||
if (clickType == ClickType.QUICK_CRAFT) {
|
||||
sendAllDataToRemote();
|
||||
}
|
||||
return;
|
||||
}
|
||||
super.clicked(i, j, clickType, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(@NotNull Player player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Overrides from here on are purely to modify the sync process to send placeholder items.
|
||||
@Override
|
||||
protected @NotNull Slot addSlot(@NotNull Slot slot) {
|
||||
slot.index = this.slots.size();
|
||||
this.slots.add(slot);
|
||||
this.lastSlots.add(ItemStack.EMPTY);
|
||||
this.remoteSlots.add(ItemStack.EMPTY);
|
||||
return slot;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull DataSlot addDataSlot(@NotNull DataSlot dataSlot) {
|
||||
this.dataSlots.add(dataSlot);
|
||||
this.remoteDataSlots.add(0);
|
||||
return dataSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addDataSlots(ContainerData containerData) {
|
||||
for (int i = 0; i < containerData.getCount(); i++) {
|
||||
this.addDataSlot(DataSlot.forContainer(containerData, i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSlotListener(@NotNull ContainerListener containerListener) {
|
||||
if (!this.containerListeners.contains(containerListener)) {
|
||||
this.containerListeners.add(containerListener);
|
||||
this.broadcastChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSynchronizer(@NotNull ContainerSynchronizer containerSynchronizer) {
|
||||
this.synchronizer = containerSynchronizer;
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAllDataToRemote() {
|
||||
for (int index = 0; index < slots.size(); ++index) {
|
||||
Slot slot = slots.get(index);
|
||||
this.remoteSlots.set(index, (slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem()).copy());
|
||||
}
|
||||
|
||||
remoteCarried = getCarried().copy();
|
||||
|
||||
for (int index = 0; index < this.dataSlots.size(); ++index) {
|
||||
this.remoteDataSlots.set(index, this.dataSlots.get(index).get());
|
||||
}
|
||||
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastCarriedItem() {
|
||||
this.remoteCarried = this.getCarried().copy();
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendCarriedChange(this, this.remoteCarried);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSlotListener(@NotNull ContainerListener containerListener) {
|
||||
this.containerListeners.remove(containerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastChanges() {
|
||||
for (int index = 0; index < this.slots.size(); ++index) {
|
||||
Slot slot = this.slots.get(index);
|
||||
ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem();
|
||||
Supplier<ItemStack> supplier = Suppliers.memoize(itemstack::copy);
|
||||
this.triggerSlotListeners(index, itemstack, supplier);
|
||||
this.synchronizeSlotToRemote(index, itemstack, supplier);
|
||||
}
|
||||
|
||||
this.synchronizeCarriedToRemote();
|
||||
|
||||
for (int index = 0; index < this.dataSlots.size(); ++index) {
|
||||
DataSlot dataSlot = this.dataSlots.get(index);
|
||||
int j = dataSlot.get();
|
||||
if (dataSlot.checkAndClearUpdateFlag()) {
|
||||
this.updateDataSlotListeners(index, j);
|
||||
}
|
||||
|
||||
this.synchronizeDataSlotToRemote(index, j);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastFullState() {
|
||||
for (int index = 0; index < this.slots.size(); ++index) {
|
||||
ItemStack itemstack = this.slots.get(index).getItem();
|
||||
this.triggerSlotListeners(index, itemstack, itemstack::copy);
|
||||
}
|
||||
|
||||
for (int index = 0; index < this.dataSlots.size(); ++index) {
|
||||
DataSlot containerproperty = this.dataSlots.get(index);
|
||||
if (containerproperty.checkAndClearUpdateFlag()) {
|
||||
this.updateDataSlotListeners(index, containerproperty.get());
|
||||
}
|
||||
}
|
||||
|
||||
this.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
private void updateDataSlotListeners(int i, int j) {
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.dataChanged(this, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerSlotListeners(int index, ItemStack itemStack, Supplier<ItemStack> supplier) {
|
||||
ItemStack itemStack1 = this.lastSlots.get(index);
|
||||
if (!ItemStack.matches(itemStack1, itemStack)) {
|
||||
ItemStack itemStack2 = supplier.get();
|
||||
this.lastSlots.set(index, itemStack2);
|
||||
|
||||
for (ContainerListener containerListener : this.containerListeners) {
|
||||
containerListener.slotChanged(this, index, itemStack2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeSlotToRemote(int i, ItemStack itemStack, Supplier<ItemStack> supplier) {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
ItemStack itemStack1 = this.remoteSlots.get(i);
|
||||
if (!ItemStack.matches(itemStack1, itemStack)) {
|
||||
ItemStack itemstack2 = supplier.get();
|
||||
this.remoteSlots.set(i, itemstack2);
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendSlotChange(this, i, itemstack2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeDataSlotToRemote(int index, int value) {
|
||||
if (!this.suppressRemoteUpdates) {
|
||||
int existing = this.remoteDataSlots.getInt(index);
|
||||
if (existing != value) {
|
||||
this.remoteDataSlots.set(index, value);
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendDataChange(this, index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void synchronizeCarriedToRemote() {
|
||||
if (!this.suppressRemoteUpdates && !ItemStack.matches(this.getCarried(), this.remoteCarried)) {
|
||||
this.remoteCarried = this.getCarried().copy();
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer.sendCarriedChange(this, this.remoteCarried);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoteCarried(ItemStack itemstack) {
|
||||
this.remoteCarried = itemstack.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suppressRemoteUpdates() {
|
||||
this.suppressRemoteUpdates = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeRemoteUpdates() {
|
||||
this.suppressRemoteUpdates = false;
|
||||
}
|
||||
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.menu;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.OpenEnderChest;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenEnderChestMenu extends OpenChestMenu<OpenEnderChest> {
|
||||
|
||||
public OpenEnderChestMenu(
|
||||
@NotNull OpenEnderChest enderChest,
|
||||
@NotNull ServerPlayer viewer,
|
||||
int containerId,
|
||||
boolean viewOnly
|
||||
) {
|
||||
super(
|
||||
com.lishid.openinv.internal.common.container.menu.OpenChestMenu.getChestMenuType(enderChest.getContainerSize()),
|
||||
containerId,
|
||||
enderChest,
|
||||
viewer,
|
||||
viewOnly
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) {
|
||||
if (viewOnly) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
// See ChestMenu
|
||||
Slot slot = this.slots.get(index);
|
||||
|
||||
if (slot.isFake() || !slot.hasItem()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack itemStack = slot.getItem();
|
||||
ItemStack original = itemStack.copy();
|
||||
|
||||
if (index < topSize) {
|
||||
if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.moveItemStackTo(itemStack, 0, topSize, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
if (itemStack.isEmpty()) {
|
||||
slot.setByPlayer(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.setChanged();
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.slot;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.slot.ContentList;
|
||||
import com.lishid.openinv.internal.common.container.slot.SlotPlaceholder;
|
||||
import com.lishid.openinv.internal.common.container.slot.placeholder.Placeholders;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A slot for equipment that displays placeholders if empty.
|
||||
*/
|
||||
public class ContentEquipment extends ContentList {
|
||||
|
||||
private final ItemStack placeholder;
|
||||
private final EquipmentSlot equipmentSlot;
|
||||
|
||||
public ContentEquipment(ServerPlayer holder, int index, EquipmentSlot equipmentSlot) {
|
||||
super(holder, index, InventoryType.SlotType.ARMOR);
|
||||
placeholder = switch (equipmentSlot) {
|
||||
case HEAD -> Placeholders.emptyHelmet;
|
||||
case CHEST -> Placeholders.emptyChestplate;
|
||||
case LEGS -> Placeholders.emptyLeggings;
|
||||
case FEET -> Placeholders.emptyBoots;
|
||||
default -> Placeholders.emptyOffHand;
|
||||
};
|
||||
this.equipmentSlot = equipmentSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHolder(@NotNull ServerPlayer holder) {
|
||||
this.items = holder.getInventory().armor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slot asSlot(Container container, int slot, int x, int y) {
|
||||
return new SlotEquipment(container, slot, x, y);
|
||||
}
|
||||
|
||||
public class SlotEquipment extends SlotPlaceholder {
|
||||
|
||||
private ServerPlayer viewer;
|
||||
|
||||
SlotEquipment(Container container, int index, int x, int y) {
|
||||
super(container, index, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOrDefault() {
|
||||
ItemStack itemStack = getItem();
|
||||
if (!itemStack.isEmpty()) {
|
||||
return itemStack;
|
||||
}
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
public EquipmentSlot getEquipmentSlot() {
|
||||
return equipmentSlot;
|
||||
}
|
||||
|
||||
public void onlyEquipmentFor(ServerPlayer viewer) {
|
||||
this.viewer = viewer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(@NotNull ItemStack itemStack) {
|
||||
if (viewer == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return equipmentSlot == EquipmentSlot.OFFHAND || viewer.getEquipmentSlotForItem(itemStack) == equipmentSlot;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.slot;
|
||||
|
||||
import com.lishid.openinv.internal.common.player.BaseOpenPlayer;
|
||||
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A slot for equipment that updates held items if necessary.
|
||||
*/
|
||||
public class ContentOffHand extends ContentEquipment {
|
||||
|
||||
private ServerPlayer holder;
|
||||
|
||||
public ContentOffHand(ServerPlayer holder, int localIndex) {
|
||||
super(holder, localIndex, EquipmentSlot.OFFHAND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHolder(@NotNull ServerPlayer holder) {
|
||||
this.items = holder.getInventory().offhand;
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryType.SlotType getSlotType() {
|
||||
return InventoryType.SlotType.QUICKBAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slot asSlot(Container container, int slot, int x, int y) {
|
||||
return new SlotEquipment(container, slot, x, y) {
|
||||
@Override
|
||||
public void setChanged() {
|
||||
if (BaseOpenPlayer.isConnected(holder.connection) && holder.containerMenu != holder.inventoryMenu) {
|
||||
holder.connection.send(
|
||||
new ClientboundContainerSetSlotPacket(
|
||||
holder.inventoryMenu.containerId,
|
||||
holder.inventoryMenu.incrementStateId(),
|
||||
InventoryMenu.SHIELD_SLOT,
|
||||
holder.getOffhandItem()
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.slot.placeholder.PlaceholderLoaderBase;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.TagParser;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.CustomModelData;
|
||||
import net.minecraft.world.item.component.DyedItemColor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CustomModelBase extends PlaceholderLoaderBase {
|
||||
|
||||
private final @NotNull CustomModelData defaultCustomModelData;
|
||||
|
||||
public CustomModelBase(@NotNull CustomModelData defaultCustomModelData) {
|
||||
this.defaultCustomModelData = defaultCustomModelData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull CompoundTag parseTag(@NotNull String itemText) throws Exception {
|
||||
return TagParser.parseTag(itemText);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addModelData(@NotNull ItemStack itemStack) {
|
||||
itemStack.set(DataComponents.CUSTOM_MODEL_DATA, defaultCustomModelData);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void hideTooltip(@NotNull ItemStack itemStack) {
|
||||
itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DyedItemColor getDye(int rgb) {
|
||||
return new DyedItemColor(rgb, false);
|
||||
}
|
||||
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.container.slot.placeholder;
|
||||
|
||||
import net.minecraft.world.item.component.CustomModelData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CustomModelPlaceholderLoader extends CustomModelBase {
|
||||
|
||||
public CustomModelPlaceholderLoader() {
|
||||
super(new CustomModelData(List.of(), List.of(), List.of("openinv:custom"), List.of()));
|
||||
}
|
||||
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.player;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OpenPlayer extends com.lishid.openinv.internal.paper1_21_5.player.OpenPlayer {
|
||||
|
||||
protected OpenPlayer(
|
||||
CraftServer server, ServerPlayer entity,
|
||||
PlayerManager manager
|
||||
) {
|
||||
super(server, entity, manager);
|
||||
}
|
||||
|
||||
@Contract("null -> new")
|
||||
@Override
|
||||
protected @NotNull CompoundTag getWritableTag(@Nullable CompoundTag oldData) {
|
||||
if (oldData == null) {
|
||||
return new CompoundTag();
|
||||
}
|
||||
|
||||
// Copy old data. This is a deep clone, so operating on it should be safe.
|
||||
oldData = oldData.copy();
|
||||
|
||||
// Remove vanilla/server data that is not written every time.
|
||||
oldData.getAllKeys()
|
||||
.removeIf(key -> RESET_TAGS.contains(key) || key.startsWith("Bukkit"));
|
||||
|
||||
return oldData;
|
||||
}
|
||||
|
||||
}
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_4.player;
|
||||
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PlayerManager extends com.lishid.openinv.internal.paper1_21_5.player.PlayerManager {
|
||||
|
||||
public PlayerManager(@NotNull Logger logger) {
|
||||
super(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseWorld(@NotNull ServerPlayer player, @NotNull CompoundTag loadedData) {
|
||||
// See PlayerList#placeNewPlayer
|
||||
World bukkitWorld;
|
||||
if (loadedData.contains("WorldUUIDMost") && loadedData.contains("WorldUUIDLeast")) {
|
||||
// Modern Bukkit world.
|
||||
bukkitWorld = Bukkit.getServer().getWorld(new UUID(loadedData.getLong("WorldUUIDMost"), loadedData.getLong("WorldUUIDLeast")));
|
||||
} else if (loadedData.contains("world", net.minecraft.nbt.Tag.TAG_STRING)) {
|
||||
// Legacy Bukkit world.
|
||||
bukkitWorld = Bukkit.getServer().getWorld(loadedData.getString("world"));
|
||||
} else {
|
||||
// Vanilla player data.
|
||||
DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, loadedData.get("Dimension")))
|
||||
.resultOrPartial(logger::warning)
|
||||
.map(player.server::getLevel)
|
||||
// If ServerLevel exists, set, otherwise move to spawn.
|
||||
.ifPresentOrElse(player::setServerLevel, () -> spawnInDefaultWorld(player.server, player));
|
||||
return;
|
||||
}
|
||||
if (bukkitWorld == null) {
|
||||
spawnInDefaultWorld(player.server, player);
|
||||
return;
|
||||
}
|
||||
player.setServerLevel(((CraftWorld) bukkitWorld).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void spawnInDefaultWorld(@NotNull MinecraftServer server, @NotNull ServerPlayer player) {
|
||||
ServerLevel level = server.getLevel(Level.OVERWORLD);
|
||||
if (level != null) {
|
||||
// Adjust player to default spawn (in keeping with Paper handling) when world not found.
|
||||
player.moveTo(player.adjustSpawnLocation(level, level.getSharedSpawnPos()).getBottomCenter(), level.getSharedSpawnAngle(), 0.0F);
|
||||
player.spawnIn(level);
|
||||
} else {
|
||||
logger.warning("Tried to load player with invalid world when no fallback was available!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlayer player) throws IllegalAccessException {
|
||||
if (bukkitEntity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitEntity.setAccessible(true);
|
||||
bukkitEntity.set(player, new OpenPlayer(player.server.server, player, this));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
plugins {
|
||||
`openinv-base`
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.capabilitiesResolution.withCapability("org.spigotmc:spigot-api") {
|
||||
val paper = candidates.firstOrNull {
|
||||
it.id.let { id ->
|
||||
id is ModuleComponentIdentifier && id.module == "paper-api"
|
||||
}
|
||||
}
|
||||
if (paper != null) {
|
||||
select(paper)
|
||||
}
|
||||
because("module is written for Paper servers")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi"))
|
||||
implementation(project(":openinvcommon"))
|
||||
implementation(project(":openinvadaptercommon"))
|
||||
|
||||
paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT")
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_5;
|
||||
|
||||
import com.lishid.openinv.internal.paper1_21_5.container.slot.placeholder.PlaceholderLoaderLegacyParse;
|
||||
import com.lishid.openinv.internal.paper1_21_5.player.PlayerManager;
|
||||
import com.lishid.openinv.util.lang.LanguageManager;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class InternalAccessor extends com.lishid.openinv.internal.common.InternalAccessor {
|
||||
|
||||
private final @NotNull PlayerManager manager;
|
||||
|
||||
public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) {
|
||||
super(logger, lang);
|
||||
manager = new PlayerManager(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PlayerManager getPlayerManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(@NotNull ConfigurationSection config) {
|
||||
ConfigurationSection placeholders = config.getConfigurationSection("placeholders");
|
||||
try {
|
||||
// Reset placeholders to defaults and try to load configuration.
|
||||
new PlaceholderLoaderLegacyParse().load(placeholders);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, "Caught exception loading placeholder overrides!", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_5.container.slot.placeholder;
|
||||
|
||||
import com.lishid.openinv.internal.common.container.slot.placeholder.PlaceholderLoader;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.craftbukkit.CraftRegistry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PlaceholderLoaderLegacyParse extends PlaceholderLoader {
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack parse(
|
||||
@Nullable ConfigurationSection section,
|
||||
@NotNull String path,
|
||||
@NotNull ItemStack defaultStack
|
||||
) throws Exception {
|
||||
if (section == null) {
|
||||
return defaultStack;
|
||||
}
|
||||
|
||||
String itemText = section.getString(path);
|
||||
|
||||
if (itemText == null) {
|
||||
return defaultStack;
|
||||
}
|
||||
|
||||
CompoundTag compoundTag = parseTag(itemText);
|
||||
Optional<ItemStack> parsed = ItemStack.parse(CraftRegistry.getMinecraftRegistry(), compoundTag);
|
||||
return parsed.filter(itemStack -> !itemStack.isEmpty()).orElse(defaultStack);
|
||||
}
|
||||
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_5.player;
|
||||
|
||||
import com.lishid.openinv.event.OpenEvents;
|
||||
import com.lishid.openinv.internal.common.player.BaseOpenPlayer;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.storage.PlayerDataStorage;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class OpenPlayer extends BaseOpenPlayer {
|
||||
|
||||
protected OpenPlayer(CraftServer server, ServerPlayer entity, PlayerManager manager) {
|
||||
super(server, entity, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
if (OpenEvents.saveCancelled(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerPlayer player = this.getHandle();
|
||||
// See net.minecraft.world.level.storage.PlayerDataStorage#save(EntityHuman)
|
||||
try {
|
||||
PlayerDataStorage worldNBTStorage = player.server.getPlayerList().playerIo;
|
||||
|
||||
CompoundTag oldData = isOnline() ? null : worldNBTStorage.load(player.getName().getString(), player.getStringUUID()).orElse(null);
|
||||
CompoundTag playerData = getWritableTag(oldData);
|
||||
|
||||
playerData = player.saveWithoutId(playerData);
|
||||
|
||||
if (oldData != null) {
|
||||
// Revert certain special data values when offline.
|
||||
revertSpecialValues(playerData, oldData);
|
||||
}
|
||||
|
||||
Path playerDataDir = worldNBTStorage.getPlayerDir().toPath();
|
||||
Path tempFile = Files.createTempFile(playerDataDir, player.getStringUUID() + "-", ".dat");
|
||||
NbtIo.writeCompressed(playerData, tempFile);
|
||||
Path dataFile = playerDataDir.resolve(player.getStringUUID() + ".dat");
|
||||
Path backupFile = playerDataDir.resolve(player.getStringUUID() + ".dat_old");
|
||||
Util.safeReplaceFile(dataFile, tempFile, backupFile);
|
||||
} catch (Exception e) {
|
||||
LogUtils.getLogger().warn("Failed to save player data for {}: {}", player.getScoreboardName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-106
@@ -1,106 +0,0 @@
|
||||
package com.lishid.openinv.internal.paper1_21_5.player;
|
||||
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtOps;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PlayerManager extends com.lishid.openinv.internal.common.player.PlayerManager {
|
||||
|
||||
public PlayerManager(@NotNull Logger logger) {
|
||||
super(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean loadData(@NotNull MinecraftServer server, @NotNull ServerPlayer player) {
|
||||
// See CraftPlayer#loadData
|
||||
CompoundTag loadedData = server.getPlayerList().playerIo.load(player).orElse(null);
|
||||
|
||||
if (loadedData == null) {
|
||||
// Exceptions with loading are logged.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read basic data into the player.
|
||||
player.load(loadedData);
|
||||
// Game type settings are also loaded separately.
|
||||
player.loadGameTypes(loadedData);
|
||||
|
||||
// World is not loaded by ServerPlayer#load(CompoundTag) on Paper.
|
||||
parseWorld(player, loadedData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void parseWorld(@NotNull ServerPlayer player, @NotNull CompoundTag loadedData) {
|
||||
// See PlayerList#placeNewPlayer
|
||||
World bukkitWorld;
|
||||
Optional<Long> msbs = loadedData.getLong("WorldUUIDMost");
|
||||
Optional<Long> lsbs = loadedData.getLong("WorldUUIDLeast");
|
||||
if (msbs.isPresent() && lsbs.isPresent()) {
|
||||
// Modern Bukkit world.
|
||||
bukkitWorld = Bukkit.getServer().getWorld(new UUID(msbs.get(), lsbs.get()));
|
||||
} else {
|
||||
Optional<String> worldName = loadedData.getString("world");
|
||||
if (worldName.isPresent()) {
|
||||
// Legacy Bukkit world.
|
||||
bukkitWorld = Bukkit.getServer().getWorld(worldName.get());
|
||||
} else {
|
||||
// Vanilla player data.
|
||||
DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, loadedData.get("Dimension")))
|
||||
.resultOrPartial(logger::warning)
|
||||
.map(player.server::getLevel)
|
||||
// If ServerLevel exists, set, otherwise move to spawn.
|
||||
.ifPresentOrElse(player::setServerLevel, () -> spawnInDefaultWorld(player.server, player));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (bukkitWorld == null) {
|
||||
spawnInDefaultWorld(player.server, player);
|
||||
return;
|
||||
}
|
||||
player.setServerLevel(((CraftWorld) bukkitWorld).getHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Player inject(@NotNull Player player) {
|
||||
try {
|
||||
ServerPlayer nmsPlayer = getHandle(player);
|
||||
if (nmsPlayer.getBukkitEntity() instanceof OpenPlayer openPlayer) {
|
||||
return openPlayer;
|
||||
}
|
||||
injectPlayer(nmsPlayer.server, nmsPlayer);
|
||||
return nmsPlayer.getBukkitEntity();
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(
|
||||
java.util.logging.Level.WARNING,
|
||||
e,
|
||||
() -> "Unable to inject ServerPlayer, certain player data may be lost when saving!"
|
||||
);
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void injectPlayer(@NotNull MinecraftServer server, @NotNull ServerPlayer player) throws IllegalAccessException {
|
||||
if (bukkitEntity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitEntity.setAccessible(true);
|
||||
|
||||
bukkitEntity.set(player, new OpenPlayer(player.server.server, player, this));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
plugins {
|
||||
alias(libs.plugins.paperweight)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
}
|
||||
|
||||
// Paper is compiled with Java 25, so we have to use a Java 25 toolchain.
|
||||
java {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(25))
|
||||
}
|
||||
|
||||
// To minimize duplicate code, the adapter for 1.21.11 is built off of this module, so we need to target Java 21.
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.release = 21
|
||||
}
|
||||
|
||||
// As a result, we have to specifically tell Gradle it's okay if our dependencies require Java 25,
|
||||
// because secretly sometimes they don't!
|
||||
configurations.matching { it.isCanBeResolved && it.name.endsWith("Classpath") }.all {
|
||||
attributes {
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 25)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":openinvapi")) {
|
||||
exclude(group = "org.spigotmc", module = "spigot-api")
|
||||
}
|
||||
implementation(project(":openinvcommon")) {
|
||||
exclude(group = "org.spigotmc", module = "spigot-api")
|
||||
}
|
||||
api(project(":openinvadapterpaper26_2")) {
|
||||
exclude(group = "io.papermc.paper", module = "dev-bundle")
|
||||
}
|
||||
|
||||
paperweight.paperDevBundle("26.1.2.build.+")
|
||||
}
|
||||
|
||||
tasks.reobfJar {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
configurations.reobf.get().outgoing.artifacts.clear()
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.lishid.openinv.internal.paper26_1;
|
||||
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.github.jikoo.openinv.internal.container.slot.InventoryFactory;
|
||||
import com.lishid.openinv.internal.paper26_1.container.AnySilentContainer;
|
||||
import com.lishid.openinv.internal.paper26_1.container.OpenEnderChest;
|
||||
import com.lishid.openinv.internal.paper26_1.player.PlayerManager;
|
||||
import com.lishid.openinv.internal.paper26_3.container.slot.placeholder.PlaceholderLoader;
|
||||
import com.github.jikoo.openinv.lang.LanguageManager;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@NullMarked
|
||||
public class InternalAccessor extends com.lishid.openinv.internal.paper26_2.InternalAccessor {
|
||||
|
||||
public InternalAccessor(Logger logger, LanguageManager lang) {
|
||||
super(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PlayerManager createPlayerManager(
|
||||
Logger logger,
|
||||
InventoryFactory<ServerPlayer, ItemStack, Container, Slot, EquipmentSlot> factory
|
||||
) {
|
||||
return new PlayerManager(logger, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnySilentContainer createAnySilentContainer(
|
||||
Logger logger,
|
||||
LanguageManager lang
|
||||
) {
|
||||
return new AnySilentContainer(logger, lang);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PlaceholderLoader createPlaceholderLoader() {
|
||||
return new com.lishid.openinv.internal.paper26_1.container.slot.placeholder.PlaceholderLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISpecialEnderChest createEnderChest(Player player) {
|
||||
return new OpenEnderChest(player);
|
||||
}
|
||||
|
||||
}
|
||||
Loaded 100 of 212 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user