mirror of
https://github.com/TotalFreedomMC/OpenInv.git
synced 2024-06-01 09:31:19 +00:00
Compare commits
90 commits
Author | SHA1 | Date | |
---|---|---|---|
1609476188 | |||
f329da29a4 | |||
1c579564bc | |||
eae4021138 | |||
be534df766 | |||
6563b4f6ce | |||
1d5a836fd0 | |||
3ba82683ec | |||
6e5c332272 | |||
1c9d133ed1 | |||
dad1e16c18 | |||
519dd7da33 | |||
1bd7932cc5 | |||
c8d16a590f | |||
352dd1bbc2 | |||
dad00d2d9c | |||
502f661be3 | |||
804d30bcc7 | |||
db8b67082b | |||
b2156edcc7 | |||
45de495699 | |||
f45d332727 | |||
41c085c4d7 | |||
3f9f382af1 | |||
9705cb156b | |||
1c45ef517f | |||
3fee84fc58 | |||
41693b5db0 | |||
00113cc4d4 | |||
788f022e74 | |||
da55790fd2 | |||
1a6d513603 | |||
a5b02ab26a | |||
0c3ce2dfb3 | |||
a1f4649a09 | |||
100d0e12cd | |||
3e629798e5 | |||
7c1f15974c | |||
d992237766 | |||
c93464e643 | |||
56afefc82b | |||
f0a66570d2 | |||
201a3578bf | |||
1228fc2de2 | |||
2561e75ae5 | |||
80661b9465 | |||
53701da34f | |||
9cf4712813 | |||
abe8fccdb5 | |||
4499bb5453 | |||
5405b7d7b9 | |||
34199d12a4 | |||
67131ab9f9 | |||
723381cb2b | |||
34e7252d77 | |||
a1b2df74cc | |||
7210f9153e | |||
dcdfac0d3b | |||
c7b4554a6c | |||
c51acb4e72 | |||
23d41cd6c8 | |||
8bc389496b | |||
1cc36d08bd | |||
c8938f451d | |||
4f2665fedc | |||
7d93bb06ad | |||
19c491411f | |||
65c6eb2693 | |||
ab1f4ace8a | |||
e7dc52bee4 | |||
a9c5799677 | |||
6d6257720a | |||
3e235fa688 | |||
dd02355ac2 | |||
4d3f5d67a8 | |||
7ad5faa2ce | |||
c28383ef36 | |||
5fbab1ab8f | |||
d97b092978 | |||
154bf56c2a | |||
d65a9caeb2 | |||
b3c4253606 | |||
b64000e89b | |||
3faf41ef18 | |||
db27d25a93 | |||
0f02e6fe66 | |||
ec07637e9f | |||
b269f3509c | |||
f2e4c8a3ad | |||
35839f1548 |
13
.github/workflows/close-issue.yml
vendored
Normal file
13
.github/workflows/close-issue.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
name: Close Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: peter-evans/close-issue@v1.0.3
|
||||
with:
|
||||
comment: "Per the notice in the readme, OpenInv is now being maintained at [Jikoo/OpenInv](https://github.com/Jikoo/OpenInv)."
|
13
.github/workflows/close-pr.yml
vendored
Normal file
13
.github/workflows/close-pr.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
name: Close Pull Request
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: superbrothers/close-pull-request@v3.1.0
|
||||
with:
|
||||
comment: "Per the notice in the readme, OpenInv is now being maintained at [Jikoo/OpenInv](https://github.com/Jikoo/OpenInv)."
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -1,11 +1,10 @@
|
|||
**/.settings
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.classpath
|
||||
**/.idea
|
||||
**/.iml
|
||||
**/target
|
||||
**/bin
|
||||
**/out
|
||||
**dependency-reduced-pom.xml
|
||||
**pom.xml.versionsBackup
|
||||
**/.idea/
|
||||
**.iml
|
||||
**/target/
|
||||
**/bin/
|
||||
**/out/
|
||||
**/dependency-reduced-pom.xml
|
||||
**/pom.xml.versionsBackup
|
||||
|
|
27
README.MD
27
README.MD
|
@ -1,3 +1,6 @@
|
|||
## Notice
|
||||
I am now maintaining OpenInv over at [Jikoo/OpenInv](https://github.com/Jikoo/OpenInv) because I needed higher levels of access to add secrets to the repository for Github Actions. It feels ruder to send an email saying what amounts to "pls op" than to redirect people to my fork, though neither option is polite. Existing issues will remain open here until resolved (you can't transfer issues across organizations/users), but any new issues in this repo will be closed without resolution.
|
||||
|
||||
## About
|
||||
OpenInv is a [Bukkit plugin](https://dev.bukkit.org/bukkit-plugins/openinv/) which allows users to open and edit anyone's inventory or ender chest - online or not!
|
||||
|
||||
|
@ -80,6 +83,14 @@ OpenInv is a [Bukkit plugin](https://dev.bukkit.org/bukkit-plugins/openinv/) whi
|
|||
<td>OpenInv.editinv</td>
|
||||
<td>Required to make changes to open inventories.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OpenInv.openonline</td>
|
||||
<td>Allows users to open online players' inventories. For compatibility reasons this is granted by the nodes OpenInv.openinv and OpenInv.openender.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OpenInv.openoffline</td>
|
||||
<td>Allows users to open offline players' inventories. For compatibility reasons this is granted by the nodes OpenInv.openinv and OpenInv.openender.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OpenInv.openender</td>
|
||||
<td>Required to use /openender.</td>
|
||||
|
@ -128,19 +139,27 @@ OpenInv is a [Bukkit plugin](https://dev.bukkit.org/bukkit-plugins/openinv/) whi
|
|||
<td>OpenInv.silent.default</td>
|
||||
<td>Cause SilentContainer to be enabled by default.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OpenInv.spectate</td>
|
||||
<td>Allows users in spectate gamemode to edit inventories.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## For Developers
|
||||
To compile, the relevant Craftbukkit/Spigot jars must be installed in your local repository using the install plugin.
|
||||
Ex: `mvn install:install-file -Dpackaging=jar -Dfile=spigot-1.11-R0.1-SNAPSHOT.jar -DgroupId=org.spigotmc -DartifactId=spigot -Dversion=1.11-R0.1-SNAPSHOT`
|
||||
Ex: `mvn install:install-file -Dpackaging=jar -Dfile=spigot-1.8-R0.1-SNAPSHOT.jar -DgroupId=org.spigotmc -DartifactId=spigot -Dversion=1.8-R0.1-SNAPSHOT`
|
||||
|
||||
To compile for a specific version or set of versions, you'll need to use a profile. Provided profiles are `latest`, `recent` (last 2 major Minecraft versions), and `all`. Select an existing profile using the `-P` argument (ex: `mvn clean package -am -P all`) or make your own. For more information, check out the [official guide](http://maven.apache.org/guides/introduction/introduction-to-profiles.html).
|
||||
To compile for a single version, specify the NMS revision you are targeting: `mvn -pl <NMS module> -am clean install`
|
||||
|
||||
The final file is target/OpenInv.jar
|
||||
To compile for a set of versions, you'll need to use a profile. The only provided profile is `all`. Select a profile using the `-P` argument: `mvn clean package -am -P all`
|
||||
|
||||
For more information, check out the [official Maven guide](http://maven.apache.org/guides/introduction/introduction-to-profiles.html).
|
||||
|
||||
The final file is `target/OpenInv.jar`
|
||||
|
||||
## License
|
||||
```
|
||||
Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
Copyright (C) 2011-2020 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
|
||||
|
|
23
api/pom.xml
23
api/pom.xml
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
@ -21,7 +21,7 @@
|
|||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.5-TF</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvapi</artifactId>
|
||||
|
@ -36,30 +36,13 @@
|
|||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -18,6 +18,7 @@ package com.lishid.openinv.util;
|
|||
|
||||
import com.lishid.openinv.internal.IInventoryAccess;
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -33,76 +34,63 @@ public class InventoryAccess implements IInventoryAccess {
|
|||
|
||||
static {
|
||||
String packageName = Bukkit.getServer().getClass().getPackage().getName();
|
||||
String version = packageName.substring(packageName.lastIndexOf('.') + 1);
|
||||
try {
|
||||
craftInventory = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftInventory");
|
||||
craftInventory = Class.forName(packageName + ".inventory.CraftInventory");
|
||||
} catch (ClassNotFoundException ignored) {}
|
||||
try {
|
||||
getInventory = craftInventory.getDeclaredMethod("getInventory");
|
||||
} catch (NoSuchMethodException ignored) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #isUsable()}
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean isUseable() {
|
||||
return isUsable();
|
||||
}
|
||||
|
||||
public static boolean isUsable() {
|
||||
return craftInventory != null && getInventory != null;
|
||||
}
|
||||
|
||||
public static boolean isPlayerInventory(@NotNull Inventory inventory) {
|
||||
if (craftInventory.isAssignableFrom(inventory.getClass())) {
|
||||
try {
|
||||
return getInventory.invoke(inventory) instanceof ISpecialPlayerInventory;
|
||||
} catch (ReflectiveOperationException ignored) {}
|
||||
}
|
||||
return grabFieldOfTypeFromObject(ISpecialPlayerInventory.class, inventory) != null;
|
||||
return getPlayerInventory(inventory) != null;
|
||||
}
|
||||
|
||||
public static ISpecialPlayerInventory getPlayerInventory(@NotNull Inventory inventory) {
|
||||
Object inv = null;
|
||||
if (craftInventory.isAssignableFrom(inventory.getClass())) {
|
||||
try {
|
||||
inv = getInventory.invoke(inventory);
|
||||
} catch (ReflectiveOperationException ignored) {}
|
||||
}
|
||||
|
||||
if (inv == null) {
|
||||
inv = grabFieldOfTypeFromObject(ISpecialPlayerInventory.class, inventory);
|
||||
}
|
||||
|
||||
if (inv instanceof ISpecialPlayerInventory) {
|
||||
return (ISpecialPlayerInventory) inv;
|
||||
}
|
||||
|
||||
return null;
|
||||
public static @Nullable ISpecialPlayerInventory getPlayerInventory(@NotNull Inventory inventory) {
|
||||
return getSpecialInventory(ISpecialPlayerInventory.class, inventory);
|
||||
}
|
||||
|
||||
public static boolean isEnderChest(@NotNull Inventory inventory) {
|
||||
if (craftInventory.isAssignableFrom(inventory.getClass())) {
|
||||
try {
|
||||
return getInventory.invoke(inventory) instanceof ISpecialEnderChest;
|
||||
} catch (ReflectiveOperationException ignored) {}
|
||||
}
|
||||
return grabFieldOfTypeFromObject(ISpecialEnderChest.class, inventory) != null;
|
||||
return getEnderChest(inventory) != null;
|
||||
}
|
||||
|
||||
public static ISpecialEnderChest getEnderChest(@NotNull Inventory inventory) {
|
||||
Object inv = null;
|
||||
if (craftInventory.isAssignableFrom(inventory.getClass())) {
|
||||
public static @Nullable ISpecialEnderChest getEnderChest(@NotNull Inventory inventory) {
|
||||
return getSpecialInventory(ISpecialEnderChest.class, inventory);
|
||||
}
|
||||
|
||||
private static <T extends ISpecialInventory> @Nullable T getSpecialInventory(@NotNull Class<T> expected, @NotNull Inventory inventory) {
|
||||
Object inv;
|
||||
if (craftInventory != null && getInventory != null && craftInventory.isAssignableFrom(inventory.getClass())) {
|
||||
try {
|
||||
inv = getInventory.invoke(inventory);
|
||||
if (expected.isInstance(inv)) {
|
||||
return expected.cast(inv);
|
||||
}
|
||||
} catch (ReflectiveOperationException ignored) {}
|
||||
}
|
||||
|
||||
if (inv == null) {
|
||||
inv = grabFieldOfTypeFromObject(ISpecialEnderChest.class, inventory);
|
||||
}
|
||||
inv = grabFieldOfTypeFromObject(expected, inventory);
|
||||
|
||||
if (inv instanceof ISpecialEnderChest) {
|
||||
return (ISpecialEnderChest) inv;
|
||||
if (expected.isInstance(inv)) {
|
||||
return expected.cast(inv);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <T> T grabFieldOfTypeFromObject(final Class<T> type, final Object object) {
|
||||
private static <T> @Nullable T grabFieldOfTypeFromObject(final Class<T> type, final Object object) {
|
||||
// Use reflection to find the IInventory
|
||||
Class<?> clazz = object.getClass();
|
||||
T result = null;
|
||||
|
@ -142,4 +130,5 @@ public class InventoryAccess implements IInventoryAccess {
|
|||
public boolean isSpecialPlayerInventory(@NotNull Inventory inventory) {
|
||||
return isPlayerInventory(inventory);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -12,21 +12,6 @@
|
|||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* *
|
||||
* Copyright (C) 2014 - 2018 Simmetrics Authors
|
||||
* Copyright (C) 2010 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.util;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
@ -21,7 +21,7 @@
|
|||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.5-TF</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvassembly</artifactId>
|
||||
|
@ -34,7 +34,7 @@
|
|||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>reactor-uberjar</id>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 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/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvcommon</artifactId>
|
||||
<name>OpenInvCommon</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvapi</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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;
|
||||
|
||||
/**
|
||||
* Abstraction for some simple cache calls.
|
||||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
public abstract class Function<V> {
|
||||
|
||||
public abstract boolean run(V value);
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
@ -20,7 +20,7 @@
|
|||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.5-TF</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
|
@ -30,28 +30,10 @@
|
|||
|
||||
<profiles>
|
||||
|
||||
<profile>
|
||||
<id>latest</id>
|
||||
<modules>
|
||||
<module>v1_14_R1</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>recent</id>
|
||||
<!-- The recent profile is for the most recent 2 versions. -->
|
||||
<modules>
|
||||
<module>v1_13_R2</module>
|
||||
<module>v1_14_R1</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>all</id>
|
||||
<modules>
|
||||
<module>v1_8_R3</module>
|
||||
<module>v1_13_R2</module>
|
||||
<module>v1_14_R1</module>
|
||||
<module>v1_16_R3</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 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/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_13_R2</artifactId>
|
||||
<name>OpenInvAdapter1_13_R2</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.13.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvcommon</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,309 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_13_R2;
|
||||
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import net.minecraft.server.v1_13_R2.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_13_R2.Block;
|
||||
import net.minecraft.server.v1_13_R2.BlockChest;
|
||||
import net.minecraft.server.v1_13_R2.BlockChestTrapped;
|
||||
import net.minecraft.server.v1_13_R2.BlockEnderChest;
|
||||
import net.minecraft.server.v1_13_R2.BlockPosition;
|
||||
import net.minecraft.server.v1_13_R2.BlockPropertyChestType;
|
||||
import net.minecraft.server.v1_13_R2.BlockShulkerBox;
|
||||
import net.minecraft.server.v1_13_R2.ChatMessage;
|
||||
import net.minecraft.server.v1_13_R2.Entity;
|
||||
import net.minecraft.server.v1_13_R2.EntityOcelot;
|
||||
import net.minecraft.server.v1_13_R2.EntityPlayer;
|
||||
import net.minecraft.server.v1_13_R2.EnumDirection;
|
||||
import net.minecraft.server.v1_13_R2.EnumGamemode;
|
||||
import net.minecraft.server.v1_13_R2.IBlockData;
|
||||
import net.minecraft.server.v1_13_R2.ITileInventory;
|
||||
import net.minecraft.server.v1_13_R2.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_13_R2.InventoryLargeChest;
|
||||
import net.minecraft.server.v1_13_R2.PlayerInteractManager;
|
||||
import net.minecraft.server.v1_13_R2.TileEntity;
|
||||
import net.minecraft.server.v1_13_R2.TileEntityChest;
|
||||
import net.minecraft.server.v1_13_R2.TileEntityEnderChest;
|
||||
import net.minecraft.server.v1_13_R2.TileEntityShulkerBox;
|
||||
import net.minecraft.server.v1_13_R2.VoxelShape;
|
||||
import net.minecraft.server.v1_13_R2.VoxelShapes;
|
||||
import net.minecraft.server.v1_13_R2.World;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AnySilentContainer implements IAnySilentContainer {
|
||||
|
||||
private Field playerInteractManagerGamemode;
|
||||
|
||||
public AnySilentContainer() {
|
||||
try {
|
||||
this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode");
|
||||
this.playerInteractManagerGamemode.setAccessible(true);
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnySilentContainer(@NotNull final org.bukkit.block.Block bukkitBlock) {
|
||||
if (bukkitBlock.getType() == Material.ENDER_CHEST) {
|
||||
return true;
|
||||
}
|
||||
BlockState state = bukkitBlock.getState();
|
||||
return state instanceof org.bukkit.block.Chest
|
||||
|| state instanceof org.bukkit.block.ShulkerBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyContainerNeeded(@NotNull final Player bukkitPlayer, @NotNull final org.bukkit.block.Block bukkitBlock) {
|
||||
|
||||
World world = PlayerDataManager.getHandle(bukkitPlayer).world;
|
||||
BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ());
|
||||
IBlockData blockData = world.getType(blockPosition);
|
||||
Block block = blockData.getBlock();
|
||||
|
||||
if (block instanceof BlockShulkerBox) {
|
||||
return this.isBlockedShulkerBox(world, blockPosition, blockData);
|
||||
}
|
||||
|
||||
if (block instanceof BlockEnderChest) {
|
||||
// Ender chests are not blocked by ocelots.
|
||||
return world.getType(blockPosition.up()).isOccluding();
|
||||
}
|
||||
|
||||
// Check if chest is blocked or has an ocelot on top
|
||||
if (this.isBlockedChest(world, blockPosition)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for matching adjacent chests that are blocked or have an ocelot on top
|
||||
BlockPropertyChestType chestType = blockData.get(BlockChest.b);
|
||||
|
||||
if (chestType == BlockPropertyChestType.SINGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.k(blockData));
|
||||
IBlockData adjacentBlockData = world.getType(adjacentBlockPosition);
|
||||
|
||||
if (adjacentBlockData.getBlock() == block) {
|
||||
|
||||
BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.b);
|
||||
|
||||
if (adjacentChestType != BlockPropertyChestType.SINGLE && chestType != adjacentChestType
|
||||
&& adjacentBlockData.get(BlockChest.FACING) == blockData.get(BlockChest.FACING)) {
|
||||
|
||||
return this.isBlockedChest(world, adjacentBlockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBlockedShulkerBox(final World world, final BlockPosition blockPosition,
|
||||
final IBlockData blockData) {
|
||||
// For reference, look at net.minecraft.server.BlockShulkerBox
|
||||
TileEntity tile = world.getTileEntity(blockPosition);
|
||||
|
||||
if (!(tile instanceof TileEntityShulkerBox)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumDirection enumDirection = blockData.get(BlockShulkerBox.a);
|
||||
if (((TileEntityShulkerBox) tile).r() == TileEntityShulkerBox.AnimationPhase.CLOSED) {
|
||||
AxisAlignedBB axisAlignedBB;
|
||||
try {
|
||||
Method method = VoxelShape.class.getMethod("a");
|
||||
axisAlignedBB = (AxisAlignedBB) method.invoke(VoxelShapes.b());
|
||||
} catch (NoSuchMethodException e) {
|
||||
axisAlignedBB = VoxelShapes.b().getBoundingBox();
|
||||
} catch (InvocationTargetException | IllegalAccessException e) {
|
||||
return false;
|
||||
}
|
||||
axisAlignedBB = axisAlignedBB
|
||||
.b(0.5F * enumDirection.getAdjacentX(), 0.5F * enumDirection.getAdjacentY(), 0.5F * enumDirection.getAdjacentZ())
|
||||
.a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(), enumDirection.getAdjacentZ());
|
||||
return !world.getCubes(null, axisAlignedBB.a(blockPosition.shift(enumDirection)));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBlockedChest(final World world, final BlockPosition blockPosition) {
|
||||
// For reference, loot at net.minecraft.server.BlockChest
|
||||
return world.getType(blockPosition.up()).isOccluding() || this.hasOcelotOnTop(world, blockPosition);
|
||||
}
|
||||
|
||||
private boolean hasOcelotOnTop(final World world, final BlockPosition blockPosition) {
|
||||
for (Entity entity : world.a(EntityOcelot.class,
|
||||
new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1,
|
||||
blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2,
|
||||
blockPosition.getZ() + 1))) {
|
||||
EntityOcelot entityOcelot = (EntityOcelot) entity;
|
||||
if (entityOcelot.isSitting()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activateContainer(@NotNull final Player bukkitPlayer, final boolean silent,
|
||||
@NotNull final org.bukkit.block.Block bukkitBlock) {
|
||||
|
||||
// Silent ender chest is API-only
|
||||
if (silent && bukkitBlock.getType() == Material.ENDER_CHEST) {
|
||||
bukkitPlayer.openInventory(bukkitPlayer.getEnderChest());
|
||||
bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED);
|
||||
return true;
|
||||
}
|
||||
|
||||
EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer);
|
||||
|
||||
final World world = player.world;
|
||||
final BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ());
|
||||
final Object tile = world.getTileEntity(blockPosition);
|
||||
|
||||
if (tile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tile instanceof TileEntityEnderChest) {
|
||||
// Anychest ender chest. See net.minecraft.server.BlockEnderChest
|
||||
InventoryEnderChest enderChest = player.getEnderChest();
|
||||
enderChest.a((TileEntityEnderChest) tile);
|
||||
player.openContainer(enderChest);
|
||||
bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(tile instanceof ITileInventory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ITileInventory tileInventory = (ITileInventory) tile;
|
||||
IBlockData blockData = world.getType(blockPosition);
|
||||
Block block = blockData.getBlock();
|
||||
|
||||
if (block instanceof BlockChest) {
|
||||
|
||||
BlockPropertyChestType chestType = blockData.get(BlockChest.b);
|
||||
|
||||
if (chestType != BlockPropertyChestType.SINGLE) {
|
||||
|
||||
BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.k(blockData));
|
||||
IBlockData adjacentBlockData = world.getType(adjacentBlockPosition);
|
||||
|
||||
if (adjacentBlockData.getBlock() == block) {
|
||||
|
||||
BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.b);
|
||||
|
||||
if (adjacentChestType != BlockPropertyChestType.SINGLE && chestType != adjacentChestType
|
||||
&& adjacentBlockData.get(BlockChest.FACING) == blockData.get(BlockChest.FACING)) {
|
||||
|
||||
TileEntity adjacentTile = world.getTileEntity(adjacentBlockPosition);
|
||||
|
||||
if (adjacentTile instanceof TileEntityChest) {
|
||||
ITileInventory rightChest = chestType == BlockPropertyChestType.RIGHT ? tileInventory : (ITileInventory) adjacentTile;
|
||||
ITileInventory leftChest = chestType == BlockPropertyChestType.RIGHT ? (ITileInventory) adjacentTile : tileInventory;
|
||||
tileInventory = new InventoryLargeChest(new ChatMessage("container.chestDouble"), rightChest, leftChest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof BlockChestTrapped) {
|
||||
bukkitPlayer.incrementStatistic(Statistic.TRAPPED_CHEST_TRIGGERED);
|
||||
} else {
|
||||
bukkitPlayer.incrementStatistic(Statistic.CHEST_OPENED);
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof BlockShulkerBox) {
|
||||
bukkitPlayer.incrementStatistic(Statistic.SHULKER_BOX_OPENED);
|
||||
}
|
||||
|
||||
// AnyChest only - SilentChest not active, container unsupported, or unnecessary.
|
||||
if (!silent || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) {
|
||||
player.openContainer(tileInventory);
|
||||
return true;
|
||||
}
|
||||
|
||||
// SilentChest requires access to setting players' gamemode directly.
|
||||
if (this.playerInteractManagerGamemode == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumGamemode gamemode = player.playerInteractManager.getGameMode();
|
||||
this.forceGameMode(player, EnumGamemode.SPECTATOR);
|
||||
player.openContainer(tileInventory);
|
||||
this.forceGameMode(player, gamemode);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivateContainer(@NotNull final Player bukkitPlayer) {
|
||||
if (this.playerInteractManagerGamemode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryView view = bukkitPlayer.getOpenInventory();
|
||||
switch (view.getType()) {
|
||||
case CHEST:
|
||||
case ENDER_CHEST:
|
||||
case SHULKER_BOX:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer);
|
||||
|
||||
EnumGamemode gamemode = player.playerInteractManager.getGameMode();
|
||||
this.forceGameMode(player, EnumGamemode.SPECTATOR);
|
||||
player.activeContainer.b(player);
|
||||
player.activeContainer = player.defaultContainer;
|
||||
this.forceGameMode(player, gamemode);
|
||||
}
|
||||
|
||||
private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) {
|
||||
if (this.playerInteractManagerGamemode == null) {
|
||||
// No need to warn repeatedly, error on startup and lack of function should be enough.
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!this.playerInteractManagerGamemode.isAccessible()) {
|
||||
// Just in case, ensure accessible.
|
||||
this.playerInteractManagerGamemode.setAccessible(true);
|
||||
}
|
||||
this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_13_R2;
|
||||
|
||||
import com.lishid.openinv.internal.IPlayerDataManager;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.server.v1_13_R2.DimensionManager;
|
||||
import net.minecraft.server.v1_13_R2.EntityPlayer;
|
||||
import net.minecraft.server.v1_13_R2.MinecraftServer;
|
||||
import net.minecraft.server.v1_13_R2.PlayerInteractManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PlayerDataManager implements IPlayerDataManager {
|
||||
|
||||
public static EntityPlayer getHandle(final Player player) {
|
||||
if (player instanceof CraftPlayer) {
|
||||
return ((CraftPlayer) player).getHandle();
|
||||
}
|
||||
|
||||
Server server = player.getServer();
|
||||
EntityPlayer nmsPlayer = null;
|
||||
|
||||
if (server instanceof CraftServer) {
|
||||
nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName());
|
||||
}
|
||||
|
||||
if (nmsPlayer == null) {
|
||||
// Could use reflection to examine fields, but it's honestly not worth the bother.
|
||||
throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation");
|
||||
}
|
||||
|
||||
return nmsPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player loadPlayer(@NotNull final OfflinePlayer offline) {
|
||||
// Ensure player has data
|
||||
if (!offline.hasPlayedBefore()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a profile and entity to load the player data
|
||||
GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName());
|
||||
MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||
EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(DimensionManager.OVERWORLD), profile,
|
||||
new PlayerInteractManager(server.getWorldServer(DimensionManager.OVERWORLD)));
|
||||
|
||||
// Get the bukkit entity
|
||||
Player target = entity.getBukkitEntity();
|
||||
if (target != null) {
|
||||
// Load data
|
||||
target.loadData();
|
||||
}
|
||||
// Return the entity
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) {
|
||||
return player.openInventory(inventory.getBukkitInventory());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,266 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_13_R2;
|
||||
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.server.v1_13_R2.AutoRecipeOutput;
|
||||
import net.minecraft.server.v1_13_R2.AutoRecipeStackManager;
|
||||
import net.minecraft.server.v1_13_R2.ContainerUtil;
|
||||
import net.minecraft.server.v1_13_R2.EntityHuman;
|
||||
import net.minecraft.server.v1_13_R2.EntityPlayer;
|
||||
import net.minecraft.server.v1_13_R2.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_13_R2.IInventory;
|
||||
import net.minecraft.server.v1_13_R2.IInventoryListener;
|
||||
import net.minecraft.server.v1_13_R2.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_13_R2.ItemStack;
|
||||
import net.minecraft.server.v1_13_R2.NonNullList;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftInventory;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SpecialEnderChest implements IInventory, ISpecialEnderChest, AutoRecipeOutput {
|
||||
|
||||
private EntityPlayer owner;
|
||||
private final IChatBaseComponent displayName;
|
||||
private final CraftInventory inventory;
|
||||
private NonNullList<ItemStack> items;
|
||||
private boolean playerOnline;
|
||||
|
||||
public SpecialEnderChest(final Player player, final Boolean online) {
|
||||
this.owner = PlayerDataManager.getHandle(player);
|
||||
this.displayName = this.owner.getEnderChest().getDisplayName();
|
||||
this.inventory = new CraftInventory(this);
|
||||
this.items = this.owner.getEnderChest().items;
|
||||
this.playerOnline = online;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getBukkitInventory() {
|
||||
return this.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUse() {
|
||||
return !this.getViewers().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOffline() {
|
||||
this.playerOnline = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOnline(@NotNull final Player player) {
|
||||
if (!this.playerOnline) {
|
||||
try {
|
||||
this.owner = PlayerDataManager.getHandle(player);
|
||||
InventoryEnderChest enderChest = owner.getEnderChest();
|
||||
for (int i = 0; i < enderChest.getSize(); ++i) {
|
||||
enderChest.setItem(i, this.items.get(i));
|
||||
}
|
||||
this.items = enderChest.items;
|
||||
} catch (Exception ignored) {}
|
||||
this.playerOnline = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
this.owner.getEnderChest().update();
|
||||
}
|
||||
|
||||
public List<ItemStack> getContents() {
|
||||
return this.items;
|
||||
}
|
||||
|
||||
public void onOpen(CraftHumanEntity who) {
|
||||
this.owner.getEnderChest().onOpen(who);
|
||||
}
|
||||
|
||||
public void onClose(CraftHumanEntity who) {
|
||||
this.owner.getEnderChest().onClose(who);
|
||||
}
|
||||
|
||||
public List<HumanEntity> getViewers() {
|
||||
return this.owner.getEnderChest().getViewers();
|
||||
}
|
||||
|
||||
public void setMaxStackSize(int i) {
|
||||
this.owner.getEnderChest().setMaxStackSize(i);
|
||||
}
|
||||
|
||||
public InventoryHolder getOwner() {
|
||||
return this.owner.getEnderChest().getOwner();
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void a(IInventoryListener iinventorylistener) {
|
||||
this.owner.getEnderChest().a(iinventorylistener);
|
||||
}
|
||||
|
||||
public void b(IInventoryListener iinventorylistener) {
|
||||
this.owner.getEnderChest().b(iinventorylistener);
|
||||
}
|
||||
|
||||
public ItemStack getItem(int i) {
|
||||
return i >= 0 && i < this.items.size() ? this.items.get(i) : ItemStack.a;
|
||||
}
|
||||
|
||||
public ItemStack splitStack(int i, int j) {
|
||||
ItemStack itemstack = ContainerUtil.a(this.items, i, j);
|
||||
if (!itemstack.isEmpty()) {
|
||||
this.update();
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
public ItemStack a(ItemStack itemstack) {
|
||||
ItemStack itemstack1 = itemstack.cloneItemStack();
|
||||
|
||||
for (int i = 0; i < this.getSize(); ++i) {
|
||||
ItemStack itemstack2 = this.getItem(i);
|
||||
if (itemstack2.isEmpty()) {
|
||||
this.setItem(i, itemstack1);
|
||||
this.update();
|
||||
return ItemStack.a;
|
||||
}
|
||||
|
||||
if (ItemStack.c(itemstack2, itemstack1)) {
|
||||
int j = Math.min(this.getMaxStackSize(), itemstack2.getMaxStackSize());
|
||||
int k = Math.min(itemstack1.getCount(), j - itemstack2.getCount());
|
||||
if (k > 0) {
|
||||
itemstack2.add(k);
|
||||
itemstack1.subtract(k);
|
||||
if (itemstack1.isEmpty()) {
|
||||
this.update();
|
||||
return ItemStack.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itemstack1.getCount() != itemstack.getCount()) {
|
||||
this.update();
|
||||
}
|
||||
|
||||
return itemstack1;
|
||||
}
|
||||
|
||||
public ItemStack splitWithoutUpdate(int i) {
|
||||
ItemStack itemstack = this.items.get(i);
|
||||
if (itemstack.isEmpty()) {
|
||||
return ItemStack.a;
|
||||
} else {
|
||||
this.items.set(i, ItemStack.a);
|
||||
return itemstack;
|
||||
}
|
||||
}
|
||||
|
||||
public void setItem(int i, ItemStack itemstack) {
|
||||
this.items.set(i, itemstack);
|
||||
if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) {
|
||||
itemstack.setCount(this.getMaxStackSize());
|
||||
}
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return this.owner.getEnderChest().getSize();
|
||||
}
|
||||
|
||||
public boolean P_() {
|
||||
|
||||
for (ItemStack itemstack : this.items) {
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IChatBaseComponent getDisplayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IChatBaseComponent getCustomName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public boolean hasCustomName() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void a(@Nullable IChatBaseComponent ichatbasecomponent) {
|
||||
// Ignored - name is always player's name.
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return 64;
|
||||
}
|
||||
|
||||
public boolean a(EntityHuman entityhuman) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void startOpen(EntityHuman entityhuman) {
|
||||
}
|
||||
|
||||
public void closeContainer(EntityHuman entityhuman) {
|
||||
}
|
||||
|
||||
public boolean b(int i, ItemStack itemstack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getProperty(int i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setProperty(int i, int j) {
|
||||
}
|
||||
|
||||
public int h() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.items.clear();
|
||||
}
|
||||
|
||||
public void a(AutoRecipeStackManager autorecipestackmanager) {
|
||||
|
||||
for (ItemStack itemstack : this.items) {
|
||||
autorecipestackmanager.b(itemstack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,719 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_13_R2;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.server.v1_13_R2.AutoRecipeStackManager;
|
||||
import net.minecraft.server.v1_13_R2.ChatMessage;
|
||||
import net.minecraft.server.v1_13_R2.ContainerUtil;
|
||||
import net.minecraft.server.v1_13_R2.CrashReport;
|
||||
import net.minecraft.server.v1_13_R2.CrashReportSystemDetails;
|
||||
import net.minecraft.server.v1_13_R2.EntityHuman;
|
||||
import net.minecraft.server.v1_13_R2.EntityPlayer;
|
||||
import net.minecraft.server.v1_13_R2.IBlockData;
|
||||
import net.minecraft.server.v1_13_R2.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_13_R2.Item;
|
||||
import net.minecraft.server.v1_13_R2.ItemArmor;
|
||||
import net.minecraft.server.v1_13_R2.ItemStack;
|
||||
import net.minecraft.server.v1_13_R2.NBTTagCompound;
|
||||
import net.minecraft.server.v1_13_R2.NBTTagList;
|
||||
import net.minecraft.server.v1_13_R2.NonNullList;
|
||||
import net.minecraft.server.v1_13_R2.PacketPlayOutSetSlot;
|
||||
import net.minecraft.server.v1_13_R2.PlayerInventory;
|
||||
import net.minecraft.server.v1_13_R2.ReportedException;
|
||||
import net.minecraft.server.v1_13_R2.World;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftInventory;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory {
|
||||
|
||||
private final CraftInventory inventory = new CraftInventory(this);
|
||||
private boolean playerOnline;
|
||||
private NonNullList<ItemStack> items, armor, extraSlots;
|
||||
private final List<NonNullList<ItemStack>> f;
|
||||
|
||||
public SpecialPlayerInventory(final Player bukkitPlayer, final Boolean online) {
|
||||
super(PlayerDataManager.getHandle(bukkitPlayer));
|
||||
this.playerOnline = online;
|
||||
this.items = this.player.inventory.items;
|
||||
this.armor = this.player.inventory.armor;
|
||||
this.extraSlots = this.player.inventory.extraSlots;
|
||||
this.f = ImmutableList.of(this.items, this.armor, this.extraSlots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOnline(@NotNull final Player player) {
|
||||
if (!this.playerOnline) {
|
||||
EntityPlayer entityPlayer = PlayerDataManager.getHandle(player);
|
||||
entityPlayer.inventory.transaction.addAll(this.transaction);
|
||||
this.player = entityPlayer;
|
||||
this.player.inventory.a(this);
|
||||
this.items = this.player.inventory.items;
|
||||
this.armor = this.player.inventory.armor;
|
||||
this.extraSlots = this.player.inventory.extraSlots;
|
||||
this.playerOnline = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean a(final EntityHuman entityhuman) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getBukkitInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int i) {
|
||||
List<ItemStack> list = this.items;
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.armor;
|
||||
} else {
|
||||
i = this.getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.extraSlots;
|
||||
} else if (list == this.armor) {
|
||||
i = this.getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
return ItemStack.a;
|
||||
}
|
||||
|
||||
return list.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChatBaseComponent getDisplayName() {
|
||||
return new ChatMessage(this.player.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomName() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getReversedArmorSlotNum(final int i) {
|
||||
if (i == 0) {
|
||||
return 3;
|
||||
}
|
||||
if (i == 1) {
|
||||
return 2;
|
||||
}
|
||||
if (i == 2) {
|
||||
return 1;
|
||||
}
|
||||
if (i == 3) {
|
||||
return 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private int getReversedItemSlotNum(final int i) {
|
||||
if (i >= 27) {
|
||||
return i - 27;
|
||||
}
|
||||
return i + 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return super.getSize() + 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUse() {
|
||||
return !this.getViewers().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int i, final ItemStack itemstack) {
|
||||
List<ItemStack> list = this.items;
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.armor;
|
||||
} else {
|
||||
i = this.getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.extraSlots;
|
||||
} else if (list == this.armor) {
|
||||
i = this.getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
this.player.drop(itemstack, true);
|
||||
return;
|
||||
}
|
||||
|
||||
list.set(i, itemstack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOffline() {
|
||||
this.playerOnline = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack splitStack(int i, final int j) {
|
||||
NonNullList<ItemStack> list = this.items;
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.armor;
|
||||
} else {
|
||||
i = this.getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.extraSlots;
|
||||
} else if (list == this.armor) {
|
||||
i = this.getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
return ItemStack.a;
|
||||
}
|
||||
|
||||
return list.get(i).isEmpty() ? ItemStack.a : ContainerUtil.a(list, i, j);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack splitWithoutUpdate(int i) {
|
||||
NonNullList<ItemStack> list = this.items;
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.armor;
|
||||
} else {
|
||||
i = this.getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
i -= list.size();
|
||||
list = this.extraSlots;
|
||||
} else if (list == this.armor) {
|
||||
i = this.getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
return ItemStack.a;
|
||||
}
|
||||
|
||||
if (!list.get(i).isEmpty()) {
|
||||
ItemStack itemstack = list.get(i);
|
||||
|
||||
list.set(i, ItemStack.a);
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
return ItemStack.a;
|
||||
}
|
||||
|
||||
public List<ItemStack> getContents() {
|
||||
List<ItemStack> combined = new ArrayList<>(this.items.size() + this.armor.size() + this.extraSlots.size());
|
||||
|
||||
for (List<ItemStack> sub : this.f) {
|
||||
combined.addAll(sub);
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
public List<ItemStack> getArmorContents() {
|
||||
return this.armor;
|
||||
}
|
||||
|
||||
public void onOpen(CraftHumanEntity who) {
|
||||
this.transaction.add(who);
|
||||
}
|
||||
|
||||
public void onClose(CraftHumanEntity who) {
|
||||
this.transaction.remove(who);
|
||||
}
|
||||
|
||||
public List<HumanEntity> getViewers() {
|
||||
return this.transaction;
|
||||
}
|
||||
|
||||
public InventoryHolder getOwner() {
|
||||
return this.player.getBukkitEntity();
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return this.player.getBukkitEntity().getLocation();
|
||||
}
|
||||
|
||||
public ItemStack getItemInHand() {
|
||||
return e(this.itemInHandIndex) ? this.items.get(this.itemInHandIndex) : ItemStack.a;
|
||||
}
|
||||
|
||||
public static int getHotbarSize() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
private boolean a(ItemStack itemstack, ItemStack itemstack1) {
|
||||
return !itemstack.isEmpty() && this.b(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize();
|
||||
}
|
||||
|
||||
private boolean b(ItemStack itemstack, ItemStack itemstack1) {
|
||||
return itemstack.getItem() == itemstack1.getItem() && ItemStack.equals(itemstack, itemstack1);
|
||||
}
|
||||
|
||||
public int canHold(ItemStack itemstack) {
|
||||
int remains = itemstack.getCount();
|
||||
|
||||
for(int i = 0; i < this.items.size(); ++i) {
|
||||
ItemStack itemstack1 = this.getItem(i);
|
||||
if (itemstack1.isEmpty()) {
|
||||
return itemstack.getCount();
|
||||
}
|
||||
|
||||
if (!this.a(itemstack, itemstack1)) {
|
||||
remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount();
|
||||
}
|
||||
|
||||
if (remains <= 0) {
|
||||
return itemstack.getCount();
|
||||
}
|
||||
}
|
||||
|
||||
return itemstack.getCount() - remains;
|
||||
}
|
||||
|
||||
public int getFirstEmptySlotIndex() {
|
||||
for(int i = 0; i < this.items.size(); ++i) {
|
||||
if (this.items.get(i).isEmpty()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void d(int i) {
|
||||
this.itemInHandIndex = this.l();
|
||||
ItemStack itemstack = this.items.get(this.itemInHandIndex);
|
||||
this.items.set(this.itemInHandIndex, this.items.get(i));
|
||||
this.items.set(i, itemstack);
|
||||
}
|
||||
|
||||
public static boolean e(int i) {
|
||||
return i >= 0 && i < 9;
|
||||
}
|
||||
|
||||
public int c(ItemStack itemstack) {
|
||||
for(int i = 0; i < this.items.size(); ++i) {
|
||||
ItemStack itemstack1 = this.items.get(i);
|
||||
if (!this.items.get(i).isEmpty() && this.b(itemstack, this.items.get(i)) && !this.items.get(i).f() && !itemstack1.hasEnchantments() && !itemstack1.hasName()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int l() {
|
||||
int i;
|
||||
int j;
|
||||
for(j = 0; j < 9; ++j) {
|
||||
i = (this.itemInHandIndex + j) % 9;
|
||||
if (this.items.get(i).isEmpty()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < 9; ++j) {
|
||||
i = (this.itemInHandIndex + j) % 9;
|
||||
if (!this.items.get(i).hasEnchantments()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return this.itemInHandIndex;
|
||||
}
|
||||
|
||||
public int a(Predicate<ItemStack> predicate, int i) {
|
||||
int j = 0;
|
||||
|
||||
int k;
|
||||
for(k = 0; k < this.getSize(); ++k) {
|
||||
ItemStack itemstack = this.getItem(k);
|
||||
if (!itemstack.isEmpty() && predicate.test(itemstack)) {
|
||||
int l = i <= 0 ? itemstack.getCount() : Math.min(i - j, itemstack.getCount());
|
||||
j += l;
|
||||
if (i != 0) {
|
||||
itemstack.subtract(l);
|
||||
if (itemstack.isEmpty()) {
|
||||
this.setItem(k, ItemStack.a);
|
||||
}
|
||||
|
||||
if (i > 0 && j >= i) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.getCarried().isEmpty() && predicate.test(this.getCarried())) {
|
||||
k = i <= 0 ? this.getCarried().getCount() : Math.min(i - j, this.getCarried().getCount());
|
||||
j += k;
|
||||
if (i != 0) {
|
||||
this.getCarried().subtract(k);
|
||||
if (this.getCarried().isEmpty()) {
|
||||
this.setCarried(ItemStack.a);
|
||||
}
|
||||
|
||||
if (i > 0 && j >= i) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
private int i(ItemStack itemstack) {
|
||||
int i = this.firstPartial(itemstack);
|
||||
if (i == -1) {
|
||||
i = this.getFirstEmptySlotIndex();
|
||||
}
|
||||
|
||||
return i == -1 ? itemstack.getCount() : this.d(i, itemstack);
|
||||
}
|
||||
|
||||
private int d(int i, ItemStack itemstack) {
|
||||
Item item = itemstack.getItem();
|
||||
int j = itemstack.getCount();
|
||||
ItemStack itemstack1 = this.getItem(i);
|
||||
if (itemstack1.isEmpty()) {
|
||||
itemstack1 = new ItemStack(item, 0);
|
||||
if (itemstack.hasTag()) {
|
||||
itemstack1.setTag(itemstack.getTag().clone());
|
||||
}
|
||||
|
||||
this.setItem(i, itemstack1);
|
||||
}
|
||||
|
||||
int k = j;
|
||||
if (j > itemstack1.getMaxStackSize() - itemstack1.getCount()) {
|
||||
k = itemstack1.getMaxStackSize() - itemstack1.getCount();
|
||||
}
|
||||
|
||||
if (k > this.getMaxStackSize() - itemstack1.getCount()) {
|
||||
k = this.getMaxStackSize() - itemstack1.getCount();
|
||||
}
|
||||
|
||||
if (k == 0) {
|
||||
return j;
|
||||
} else {
|
||||
j -= k;
|
||||
itemstack1.add(k);
|
||||
itemstack1.d(5);
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
public int firstPartial(ItemStack itemstack) {
|
||||
if (this.a(this.getItem(this.itemInHandIndex), itemstack)) {
|
||||
return this.itemInHandIndex;
|
||||
} else if (this.a(this.getItem(40), itemstack)) {
|
||||
return 40;
|
||||
} else {
|
||||
for(int i = 0; i < this.items.size(); ++i) {
|
||||
if (this.a(this.items.get(i), itemstack)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void p() {
|
||||
|
||||
for (NonNullList<ItemStack> itemStacks : this.f) {
|
||||
for (int i = 0; i < itemStacks.size(); ++i) {
|
||||
if (!itemStacks.get(i).isEmpty()) {
|
||||
itemStacks.get(i).a(this.player.world, this.player, i, this.itemInHandIndex == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean pickup(ItemStack itemstack) {
|
||||
return this.c(-1, itemstack);
|
||||
}
|
||||
|
||||
public boolean c(int i, ItemStack itemstack) {
|
||||
if (itemstack.isEmpty()) {
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
if (itemstack.f()) {
|
||||
if (i == -1) {
|
||||
i = this.getFirstEmptySlotIndex();
|
||||
}
|
||||
|
||||
if (i >= 0) {
|
||||
this.items.set(i, itemstack.cloneItemStack());
|
||||
this.items.get(i).d(5);
|
||||
itemstack.setCount(0);
|
||||
return true;
|
||||
} else if (this.player.abilities.canInstantlyBuild) {
|
||||
itemstack.setCount(0);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
int j;
|
||||
do {
|
||||
j = itemstack.getCount();
|
||||
if (i == -1) {
|
||||
itemstack.setCount(this.i(itemstack));
|
||||
} else {
|
||||
itemstack.setCount(this.d(i, itemstack));
|
||||
}
|
||||
} while(!itemstack.isEmpty() && itemstack.getCount() < j);
|
||||
|
||||
if (itemstack.getCount() == j && this.player.abilities.canInstantlyBuild) {
|
||||
itemstack.setCount(0);
|
||||
return true;
|
||||
} else {
|
||||
return itemstack.getCount() < j;
|
||||
}
|
||||
}
|
||||
} catch (Throwable var6) {
|
||||
CrashReport crashreport = CrashReport.a(var6, "Adding item to inventory");
|
||||
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Item being added");
|
||||
crashreportsystemdetails.a("Item ID", Item.getId(itemstack.getItem()));
|
||||
crashreportsystemdetails.a("Item data", itemstack.getDamage());
|
||||
crashreportsystemdetails.a("Item name", () -> itemstack.getName().getString());
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void a(World world, ItemStack itemstack) {
|
||||
if (!world.isClientSide) {
|
||||
while(!itemstack.isEmpty()) {
|
||||
int i = this.firstPartial(itemstack);
|
||||
if (i == -1) {
|
||||
i = this.getFirstEmptySlotIndex();
|
||||
}
|
||||
|
||||
if (i == -1) {
|
||||
this.player.drop(itemstack, false);
|
||||
break;
|
||||
}
|
||||
|
||||
int j = itemstack.getMaxStackSize() - this.getItem(i).getCount();
|
||||
if (this.c(i, itemstack.cloneAndSubtract(j))) {
|
||||
((EntityPlayer)this.player).playerConnection.sendPacket(new PacketPlayOutSetSlot(-2, i, this.getItem(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void f(ItemStack itemstack) {
|
||||
|
||||
for (NonNullList<ItemStack> nonnulllist : this.f) {
|
||||
for (int i = 0; i < nonnulllist.size(); ++i) {
|
||||
if (nonnulllist.get(i) == itemstack) {
|
||||
nonnulllist.set(i, ItemStack.a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float a(IBlockData iblockdata) {
|
||||
return this.items.get(this.itemInHandIndex).a(iblockdata);
|
||||
}
|
||||
|
||||
public NBTTagList a(NBTTagList nbttaglist) {
|
||||
NBTTagCompound nbttagcompound;
|
||||
int i;
|
||||
for(i = 0; i < this.items.size(); ++i) {
|
||||
if (!this.items.get(i).isEmpty()) {
|
||||
nbttagcompound = new NBTTagCompound();
|
||||
nbttagcompound.setByte("Slot", (byte) i);
|
||||
this.items.get(i).save(nbttagcompound);
|
||||
nbttaglist.add(nbttagcompound);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < this.armor.size(); ++i) {
|
||||
if (!this.armor.get(i).isEmpty()) {
|
||||
nbttagcompound = new NBTTagCompound();
|
||||
nbttagcompound.setByte("Slot", (byte) (i + 100));
|
||||
this.armor.get(i).save(nbttagcompound);
|
||||
nbttaglist.add(nbttagcompound);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < this.extraSlots.size(); ++i) {
|
||||
if (!this.extraSlots.get(i).isEmpty()) {
|
||||
nbttagcompound = new NBTTagCompound();
|
||||
nbttagcompound.setByte("Slot", (byte) (i + 150));
|
||||
this.extraSlots.get(i).save(nbttagcompound);
|
||||
nbttaglist.add(nbttagcompound);
|
||||
}
|
||||
}
|
||||
|
||||
return nbttaglist;
|
||||
}
|
||||
|
||||
public void b(NBTTagList nbttaglist) {
|
||||
this.items.clear();
|
||||
this.armor.clear();
|
||||
this.extraSlots.clear();
|
||||
|
||||
for(int i = 0; i < nbttaglist.size(); ++i) {
|
||||
NBTTagCompound nbttagcompound = nbttaglist.getCompound(i);
|
||||
int j = nbttagcompound.getByte("Slot") & 255;
|
||||
ItemStack itemstack = ItemStack.a(nbttagcompound);
|
||||
if (!itemstack.isEmpty()) {
|
||||
if (j < this.items.size()) {
|
||||
this.items.set(j, itemstack);
|
||||
} else if (j >= 100 && j < this.armor.size() + 100) {
|
||||
this.armor.set(j - 100, itemstack);
|
||||
} else if (j >= 150 && j < this.extraSlots.size() + 150) {
|
||||
this.extraSlots.set(j - 150, itemstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean P_() {
|
||||
Iterator iterator = this.items.iterator();
|
||||
|
||||
ItemStack itemstack;
|
||||
while(iterator.hasNext()) {
|
||||
itemstack = (ItemStack)iterator.next();
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
iterator = this.armor.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
itemstack = (ItemStack)iterator.next();
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
iterator = this.extraSlots.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
itemstack = (ItemStack)iterator.next();
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IChatBaseComponent getCustomName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean b(IBlockData iblockdata) {
|
||||
return this.getItem(this.itemInHandIndex).b(iblockdata);
|
||||
}
|
||||
|
||||
public void a(float f) {
|
||||
if (f > 0.0F) {
|
||||
f /= 4.0F;
|
||||
if (f < 1.0F) {
|
||||
f = 1.0F;
|
||||
}
|
||||
|
||||
for (ItemStack itemstack : this.armor) {
|
||||
if (itemstack.getItem() instanceof ItemArmor) {
|
||||
itemstack.damage((int) f, this.player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dropContents() {
|
||||
for (NonNullList<ItemStack> itemStacks : this.f) {
|
||||
for (int i = 0; i < itemStacks.size(); ++i) {
|
||||
ItemStack itemstack = itemStacks.get(i);
|
||||
if (!itemstack.isEmpty()) {
|
||||
itemStacks.set(i, ItemStack.a);
|
||||
this.player.a(itemstack, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean h(ItemStack itemstack) {
|
||||
return this.f.stream().flatMap(NonNullList::stream).anyMatch(itemStack1 -> !itemStack1.isEmpty() && itemStack1.doMaterialsMatch(itemstack));
|
||||
}
|
||||
|
||||
public void a(PlayerInventory playerinventory) {
|
||||
for (int i = 0; i < playerinventory.getSize(); ++i) {
|
||||
this.setItem(i, playerinventory.getItem(i));
|
||||
}
|
||||
|
||||
this.itemInHandIndex = playerinventory.itemInHandIndex;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.f.forEach(NonNullList::clear);
|
||||
}
|
||||
|
||||
public void a(AutoRecipeStackManager autorecipestackmanager) {
|
||||
for (ItemStack itemstack : this.items) {
|
||||
autorecipestackmanager.a(itemstack);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 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.internal.v1_14_R1;
|
||||
|
||||
import com.lishid.openinv.internal.IPlayerDataManager;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.server.v1_14_R1.ChatComponentText;
|
||||
import net.minecraft.server.v1_14_R1.Container;
|
||||
import net.minecraft.server.v1_14_R1.Containers;
|
||||
import net.minecraft.server.v1_14_R1.DimensionManager;
|
||||
import net.minecraft.server.v1_14_R1.EntityHuman;
|
||||
import net.minecraft.server.v1_14_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_14_R1.MinecraftServer;
|
||||
import net.minecraft.server.v1_14_R1.PacketPlayOutOpenWindow;
|
||||
import net.minecraft.server.v1_14_R1.PlayerInteractManager;
|
||||
import net.minecraft.server.v1_14_R1.PlayerInventory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.event.CraftEventFactory;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftContainer;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PlayerDataManager implements IPlayerDataManager {
|
||||
|
||||
public static EntityPlayer getHandle(final Player player) {
|
||||
if (player instanceof CraftPlayer) {
|
||||
return ((CraftPlayer) player).getHandle();
|
||||
}
|
||||
|
||||
Server server = player.getServer();
|
||||
EntityPlayer nmsPlayer = null;
|
||||
|
||||
if (server instanceof CraftServer) {
|
||||
nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName());
|
||||
}
|
||||
|
||||
if (nmsPlayer == null) {
|
||||
// Could use reflection to examine fields, but it's honestly not worth the bother.
|
||||
throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation");
|
||||
}
|
||||
|
||||
return nmsPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player loadPlayer(@NotNull final OfflinePlayer offline) {
|
||||
// Ensure player has data
|
||||
if (!offline.hasPlayedBefore()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a profile and entity to load the player data
|
||||
GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName());
|
||||
MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||
EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(DimensionManager.OVERWORLD), profile,
|
||||
new PlayerInteractManager(server.getWorldServer(DimensionManager.OVERWORLD)));
|
||||
|
||||
// Get the bukkit entity
|
||||
Player target = entity.getBukkitEntity();
|
||||
if (target != null) {
|
||||
// Load data
|
||||
target.loadData();
|
||||
}
|
||||
// Return the entity
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) {
|
||||
|
||||
EntityPlayer nmsPlayer = getHandle(player);
|
||||
|
||||
if (nmsPlayer == null || nmsPlayer.playerConnection == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String title;
|
||||
if (inventory instanceof SpecialEnderChest) {
|
||||
HumanEntity owner = (HumanEntity) ((SpecialEnderChest) inventory).getBukkitOwner();
|
||||
title = (owner.getName() != null ? owner.getName() : owner.getUniqueId().toString()) + "'s Ender Chest";
|
||||
} else if (inventory instanceof SpecialPlayerInventory) {
|
||||
EntityHuman owner = ((PlayerInventory) inventory).player;
|
||||
title = (owner.getName() != null ? owner.getName() : owner.getUniqueID().toString()) + "'s Inventory";
|
||||
} else {
|
||||
return player.openInventory(inventory.getBukkitInventory());
|
||||
}
|
||||
|
||||
Container container = new CraftContainer(new InventoryView() {
|
||||
@Override
|
||||
public @NotNull Inventory getTopInventory() {
|
||||
return inventory.getBukkitInventory();
|
||||
}
|
||||
@Override
|
||||
public @NotNull Inventory getBottomInventory() {
|
||||
return player.getInventory();
|
||||
}
|
||||
@Override
|
||||
public @NotNull HumanEntity getPlayer() {
|
||||
return player;
|
||||
}
|
||||
@Override
|
||||
public @NotNull InventoryType getType() {
|
||||
return inventory.getBukkitInventory().getType();
|
||||
}
|
||||
@Override
|
||||
public @NotNull String getTitle() {
|
||||
return title;
|
||||
}
|
||||
}, nmsPlayer, nmsPlayer.nextContainerCounter()) {
|
||||
@Override
|
||||
public Containers<?> getType() {
|
||||
return inventory instanceof SpecialEnderChest ? Containers.GENERIC_9X3 : Containers.GENERIC_9X5;
|
||||
}
|
||||
};
|
||||
|
||||
container.setTitle(new ChatComponentText(title));
|
||||
container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container);
|
||||
|
||||
if (container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
nmsPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(),
|
||||
new ChatComponentText(container.getBukkitView().getTitle())));
|
||||
nmsPlayer.activeContainer = container;
|
||||
container.addSlotListener(nmsPlayer);
|
||||
|
||||
return container.getBukkitView();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
@ -22,23 +22,23 @@
|
|||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.5-TF</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_14_R1</artifactId>
|
||||
<name>OpenInvAdapter1_14_R1</name>
|
||||
<artifactId>openinvadapter1_16_R3</artifactId>
|
||||
<name>OpenInvAdapter1_16_R3</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.14.3-R0.1-SNAPSHOT</version>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvcommon</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
<version>4.1.5-TF</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
|
@ -72,4 +72,4 @@
|
|||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -14,48 +14,52 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.internal.v1_14_R1;
|
||||
package com.lishid.openinv.internal.v1_16_R3;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import java.lang.reflect.Field;
|
||||
import javax.annotation.Nullable;
|
||||
import net.minecraft.server.v1_14_R1.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_14_R1.Block;
|
||||
import net.minecraft.server.v1_14_R1.BlockBarrel;
|
||||
import net.minecraft.server.v1_14_R1.BlockChest;
|
||||
import net.minecraft.server.v1_14_R1.BlockChestTrapped;
|
||||
import net.minecraft.server.v1_14_R1.BlockEnderChest;
|
||||
import net.minecraft.server.v1_14_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_14_R1.BlockPropertyChestType;
|
||||
import net.minecraft.server.v1_14_R1.BlockShulkerBox;
|
||||
import net.minecraft.server.v1_14_R1.ChatMessage;
|
||||
import net.minecraft.server.v1_14_R1.Container;
|
||||
import net.minecraft.server.v1_14_R1.ContainerChest;
|
||||
import net.minecraft.server.v1_14_R1.Entity;
|
||||
import net.minecraft.server.v1_14_R1.EntityCat;
|
||||
import net.minecraft.server.v1_14_R1.EntityHuman;
|
||||
import net.minecraft.server.v1_14_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_14_R1.EnumDirection;
|
||||
import net.minecraft.server.v1_14_R1.EnumGamemode;
|
||||
import net.minecraft.server.v1_14_R1.IBlockData;
|
||||
import net.minecraft.server.v1_14_R1.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_14_R1.ITileInventory;
|
||||
import net.minecraft.server.v1_14_R1.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_14_R1.InventoryLargeChest;
|
||||
import net.minecraft.server.v1_14_R1.PlayerInteractManager;
|
||||
import net.minecraft.server.v1_14_R1.PlayerInventory;
|
||||
import net.minecraft.server.v1_14_R1.TileEntity;
|
||||
import net.minecraft.server.v1_14_R1.TileEntityChest;
|
||||
import net.minecraft.server.v1_14_R1.TileEntityEnderChest;
|
||||
import net.minecraft.server.v1_14_R1.TileEntityShulkerBox;
|
||||
import net.minecraft.server.v1_14_R1.TileInventory;
|
||||
import net.minecraft.server.v1_14_R1.VoxelShapes;
|
||||
import net.minecraft.server.v1_14_R1.World;
|
||||
import net.minecraft.server.v1_16_R3.Block;
|
||||
import net.minecraft.server.v1_16_R3.BlockBarrel;
|
||||
import net.minecraft.server.v1_16_R3.BlockChest;
|
||||
import net.minecraft.server.v1_16_R3.BlockChestTrapped;
|
||||
import net.minecraft.server.v1_16_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_16_R3.BlockPropertyChestType;
|
||||
import net.minecraft.server.v1_16_R3.BlockShulkerBox;
|
||||
import net.minecraft.server.v1_16_R3.ChatMessage;
|
||||
import net.minecraft.server.v1_16_R3.Container;
|
||||
import net.minecraft.server.v1_16_R3.ContainerChest;
|
||||
import net.minecraft.server.v1_16_R3.Containers;
|
||||
import net.minecraft.server.v1_16_R3.EntityHuman;
|
||||
import net.minecraft.server.v1_16_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_16_R3.EnumGamemode;
|
||||
import net.minecraft.server.v1_16_R3.IBlockData;
|
||||
import net.minecraft.server.v1_16_R3.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_16_R3.ITileInventory;
|
||||
import net.minecraft.server.v1_16_R3.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_16_R3.InventoryLargeChest;
|
||||
import net.minecraft.server.v1_16_R3.PlayerInteractManager;
|
||||
import net.minecraft.server.v1_16_R3.PlayerInventory;
|
||||
import net.minecraft.server.v1_16_R3.TileEntity;
|
||||
import net.minecraft.server.v1_16_R3.TileEntityChest;
|
||||
import net.minecraft.server.v1_16_R3.TileEntityEnderChest;
|
||||
import net.minecraft.server.v1_16_R3.TileEntityLootable;
|
||||
import net.minecraft.server.v1_16_R3.TileInventory;
|
||||
import net.minecraft.server.v1_16_R3.World;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.block.Barrel;
|
||||
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.Directional;
|
||||
import org.bukkit.block.data.type.Chest;
|
||||
import org.bukkit.entity.Cat;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AnySilentContainer implements IAnySilentContainer {
|
||||
|
@ -84,88 +88,80 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyContainerNeeded(@NotNull final Player p, @NotNull final org.bukkit.block.Block bukkitBlock) {
|
||||
EntityPlayer player = PlayerDataManager.getHandle(p);
|
||||
World world = player.world;
|
||||
BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ());
|
||||
IBlockData blockData = world.getType(blockPosition);
|
||||
Block block = blockData.getBlock();
|
||||
public boolean isAnyContainerNeeded(@NotNull final Player p, @NotNull final org.bukkit.block.Block block) {
|
||||
BlockState blockState = block.getState();
|
||||
|
||||
if (block instanceof BlockShulkerBox) {
|
||||
return this.isBlockedShulkerBox(world, blockPosition, blockData);
|
||||
// Barrels do not require AnyContainer.
|
||||
if (blockState instanceof Barrel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block instanceof BlockEnderChest) {
|
||||
// Ender chests are not blocked by ocelots.
|
||||
return world.getType(blockPosition.up()).isOccluding(world, blockPosition);
|
||||
// Enderchests require a non-occluding block on top to open.
|
||||
if (blockState instanceof EnderChest) {
|
||||
return block.getRelative(0, 1, 0).getType().isOccluding();
|
||||
}
|
||||
|
||||
// Check if chest is blocked or has an ocelot on top
|
||||
if (this.isBlockedChest(world, blockPosition)) {
|
||||
// Shulker boxes require 1/2 a block clear in the direction they open.
|
||||
if (blockState instanceof ShulkerBox) {
|
||||
BoundingBox boundingBox = block.getBoundingBox();
|
||||
if (boundingBox.getVolume() > 1) {
|
||||
// Shulker box is already open.
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Directional)) {
|
||||
// Shouldn't be possible. Just in case, demand AnyChest.
|
||||
return true;
|
||||
}
|
||||
|
||||
Directional directional = (Directional) blockData;
|
||||
BlockFace face = directional.getFacing();
|
||||
boundingBox.shift(face.getDirection());
|
||||
// Return whether or not bounding boxes overlap.
|
||||
return block.getRelative(face, 1).getBoundingBox().overlaps(boundingBox);
|
||||
}
|
||||
|
||||
if (!(blockState instanceof org.bukkit.block.Chest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isBlockedChest(block)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for matching adjacent chests that are blocked or have an ocelot on top
|
||||
BlockPropertyChestType chestType = blockData.get(BlockChest.b);
|
||||
|
||||
if (chestType == BlockPropertyChestType.SINGLE) {
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Chest) || ((Chest) blockData).getType() == Chest.Type.SINGLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.j(blockData));
|
||||
IBlockData adjacentBlockData = world.getType(adjacentBlockPosition);
|
||||
Chest chest = (Chest) blockData;
|
||||
int ordinal = (chest.getFacing().ordinal() + 4 + (chest.getType() == Chest.Type.RIGHT ? -1 : 1)) % 4;
|
||||
BlockFace relativeFace = BlockFace.values()[ordinal];
|
||||
org.bukkit.block.Block relative = block.getRelative(relativeFace);
|
||||
|
||||
if (adjacentBlockData.getBlock() == block) {
|
||||
|
||||
BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.b);
|
||||
|
||||
if (adjacentChestType != BlockPropertyChestType.SINGLE && chestType != adjacentChestType
|
||||
&& adjacentBlockData.get(BlockChest.FACING) == blockData.get(BlockChest.FACING)) {
|
||||
|
||||
return this.isBlockedChest(world, adjacentBlockPosition);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBlockedShulkerBox(final World world, final BlockPosition blockPosition,
|
||||
final IBlockData blockData) {
|
||||
// For reference, look at net.minecraft.server.BlockShulkerBox
|
||||
TileEntity tile = world.getTileEntity(blockPosition);
|
||||
|
||||
if (!(tile instanceof TileEntityShulkerBox)) {
|
||||
if (relative.getType() != block.getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumDirection enumDirection = blockData.get(BlockShulkerBox.a);
|
||||
if (((TileEntityShulkerBox) tile).s() == TileEntityShulkerBox.AnimationPhase.CLOSED) {
|
||||
AxisAlignedBB axisAlignedBB = VoxelShapes.b().getBoundingBox()
|
||||
.b(0.5F * enumDirection.getAdjacentX(), 0.5F * enumDirection.getAdjacentY(), 0.5F * enumDirection.getAdjacentZ())
|
||||
.a(enumDirection.getAdjacentX(), enumDirection.getAdjacentY(), enumDirection.getAdjacentZ());
|
||||
return !world.getCubes(null, axisAlignedBB.a(blockPosition.shift(enumDirection)));
|
||||
BlockData relativeData = relative.getBlockData();
|
||||
if (!(relativeData instanceof Chest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBlockedChest(final World world, final BlockPosition blockPosition) {
|
||||
// For reference, loot at net.minecraft.server.BlockChest
|
||||
return world.getType(blockPosition.up()).isOccluding(world, blockPosition) || this.hasOcelotOnTop(world, blockPosition);
|
||||
}
|
||||
|
||||
private boolean hasOcelotOnTop(final World world, final BlockPosition blockPosition) {
|
||||
for (Entity entity : world.a(EntityCat.class,
|
||||
new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1,
|
||||
blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2,
|
||||
blockPosition.getZ() + 1))) {
|
||||
EntityCat entityCat = (EntityCat) entity;
|
||||
if (entityCat.isSitting()) {
|
||||
return true;
|
||||
}
|
||||
Chest relativeChest = (Chest) relativeData;
|
||||
if (relativeChest.getFacing() != chest.getFacing()
|
||||
|| relativeChest.getType() != (chest.getType() == Chest.Type.RIGHT ? Chest.Type.LEFT : Chest.Type.RIGHT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return isBlockedChest(relative);
|
||||
}
|
||||
|
||||
private boolean isBlockedChest(org.bukkit.block.Block block) {
|
||||
org.bukkit.block.Block relative = block.getRelative(0, 1, 0);
|
||||
return relative.getType().isOccluding()
|
||||
|| block.getWorld().getNearbyEntities(BoundingBox.of(relative), entity -> entity instanceof Cat).size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -183,7 +179,7 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
|
||||
final World world = player.world;
|
||||
final BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ());
|
||||
final Object tile = world.getTileEntity(blockPosition);
|
||||
final TileEntity tile = world.getTileEntity(blockPosition);
|
||||
|
||||
if (tile == null) {
|
||||
return false;
|
||||
|
@ -193,8 +189,11 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
// Anychest ender chest. See net.minecraft.server.BlockEnderChest
|
||||
InventoryEnderChest enderChest = player.getEnderChest();
|
||||
enderChest.a((TileEntityEnderChest) tile);
|
||||
player.openContainer(new TileInventory((containerCounter, playerInventory, ignored) ->
|
||||
ContainerChest.a(containerCounter, playerInventory, enderChest), BlockEnderChest.d));
|
||||
player.openContainer(new TileInventory((containerCounter, playerInventory, ignored) -> {
|
||||
Containers<?> containers = PlayerDataManager.getContainers(enderChest.getSize());
|
||||
int rows = enderChest.getSize() / 9;
|
||||
return new ContainerChest(containers, containerCounter, playerInventory, enderChest, rows);
|
||||
}, new ChatMessage("container.enderchest")));
|
||||
bukkitPlayer.incrementStatistic(Statistic.ENDERCHEST_OPENED);
|
||||
return true;
|
||||
}
|
||||
|
@ -209,16 +208,16 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
|
||||
if (block instanceof BlockChest) {
|
||||
|
||||
BlockPropertyChestType chestType = blockData.get(BlockChest.b);
|
||||
BlockPropertyChestType chestType = blockData.get(BlockChest.c);
|
||||
|
||||
if (chestType != BlockPropertyChestType.SINGLE) {
|
||||
|
||||
BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.j(blockData));
|
||||
BlockPosition adjacentBlockPosition = blockPosition.shift(BlockChest.h(blockData));
|
||||
IBlockData adjacentBlockData = world.getType(adjacentBlockPosition);
|
||||
|
||||
if (adjacentBlockData.getBlock() == block) {
|
||||
|
||||
BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.b);
|
||||
BlockPropertyChestType adjacentChestType = adjacentBlockData.get(BlockChest.c);
|
||||
|
||||
if (adjacentChestType != BlockPropertyChestType.SINGLE && chestType != adjacentChestType
|
||||
&& adjacentBlockData.get(BlockChest.FACING) == blockData.get(BlockChest.FACING)) {
|
||||
|
@ -228,19 +227,26 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
if (adjacentTile instanceof TileEntityChest && tileInventory instanceof TileEntityChest) {
|
||||
TileEntityChest rightChest = chestType == BlockPropertyChestType.RIGHT ? ((TileEntityChest) tileInventory) : (TileEntityChest) adjacentTile;
|
||||
TileEntityChest leftChest = chestType == BlockPropertyChestType.RIGHT ? (TileEntityChest) adjacentTile : ((TileEntityChest) tileInventory);
|
||||
|
||||
if (silentchest && (rightChest.lootTable != null || leftChest.lootTable != null)) {
|
||||
OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated");
|
||||
return false;
|
||||
}
|
||||
|
||||
tileInventory = new ITileInventory() {
|
||||
@Nullable
|
||||
public Container createMenu(int containerCounter, PlayerInventory playerInventory, EntityHuman entityHuman) {
|
||||
if (leftChest.e(entityHuman) && rightChest.e(entityHuman)) {
|
||||
leftChest.d(playerInventory.player);
|
||||
rightChest.d(playerInventory.player);
|
||||
return ContainerChest.b(containerCounter, playerInventory, new InventoryLargeChest(rightChest, leftChest));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
leftChest.d(playerInventory.player);
|
||||
rightChest.d(playerInventory.player);
|
||||
return ContainerChest.b(containerCounter, playerInventory, new InventoryLargeChest(rightChest, leftChest));
|
||||
}
|
||||
|
||||
public IChatBaseComponent getScoreboardDisplayName() {
|
||||
if (leftChest.hasCustomName()) {
|
||||
return leftChest.getScoreboardDisplayName();
|
||||
}
|
||||
if (rightChest.hasCustomName()) {
|
||||
return rightChest.getScoreboardDisplayName();
|
||||
}
|
||||
return new ChatMessage("container.chestDouble");
|
||||
}
|
||||
};
|
||||
|
@ -275,6 +281,14 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (tile instanceof TileEntityLootable) {
|
||||
TileEntityLootable lootable = (TileEntityLootable) tile;
|
||||
if (lootable.lootTable != null) {
|
||||
OpenInv.getPlugin(OpenInv.class).sendSystemMessage(bukkitPlayer, "messages.error.lootNotGenerated");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
EnumGamemode gamemode = player.playerInteractManager.getGameMode();
|
||||
this.forceGameMode(player, EnumGamemode.SPECTATOR);
|
||||
player.openContainer(tileInventory);
|
||||
|
@ -294,9 +308,9 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
case ENDER_CHEST:
|
||||
case SHULKER_BOX:
|
||||
case BARREL:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer);
|
||||
|
@ -304,6 +318,8 @@ public class AnySilentContainer implements IAnySilentContainer {
|
|||
EnumGamemode gamemode = player.playerInteractManager.getGameMode();
|
||||
this.forceGameMode(player, EnumGamemode.SPECTATOR);
|
||||
player.activeContainer.b(player);
|
||||
player.activeContainer.a(player, false);
|
||||
player.activeContainer.transferTo(player.defaultContainer, player.getBukkitEntity());
|
||||
player.activeContainer = player.defaultContainer;
|
||||
this.forceGameMode(player, gamemode);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.lishid.openinv.internal.v1_16_R3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import net.minecraft.server.v1_16_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_16_R3.NBTCompressedStreamTools;
|
||||
import net.minecraft.server.v1_16_R3.NBTTagCompound;
|
||||
import net.minecraft.server.v1_16_R3.WorldNBTStorage;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
|
||||
|
||||
public class OpenPlayer extends CraftPlayer {
|
||||
|
||||
public OpenPlayer(CraftServer server, EntityPlayer entity) {
|
||||
super(server, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
super.saveData();
|
||||
EntityPlayer player = this.getHandle();
|
||||
// See net.minecraft.server.WorldNBTStorage#save(EntityPlayer)
|
||||
try {
|
||||
WorldNBTStorage worldNBTStorage = player.server.getPlayerList().playerFileData;
|
||||
|
||||
NBTTagCompound playerData = player.save(new NBTTagCompound());
|
||||
|
||||
if (!isOnline()) {
|
||||
// Special case: save old vehicle data
|
||||
NBTTagCompound oldData = worldNBTStorage.load(player);
|
||||
|
||||
if (oldData != null && oldData.hasKeyOfType("RootVehicle", 10)) {
|
||||
// See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound)
|
||||
playerData.set("RootVehicle", oldData.getCompound("RootVehicle"));
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat.tmp");
|
||||
File file1 = new File(worldNBTStorage.getPlayerDir(), player.getUniqueIDString() + ".dat");
|
||||
|
||||
NBTCompressedStreamTools.a(playerData, new FileOutputStream(file));
|
||||
|
||||
if (file1.exists() && !file1.delete() || !file.renameTo(file1)) {
|
||||
LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LogManager.getLogger().warn("Failed to save player data for {}", player.getDisplayName().getString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2020 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.internal.v1_16_R3;
|
||||
|
||||
import com.lishid.openinv.internal.IPlayerDataManager;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.internal.OpenInventoryView;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import java.lang.reflect.Field;
|
||||
import net.minecraft.server.v1_16_R3.ChatComponentText;
|
||||
import net.minecraft.server.v1_16_R3.Container;
|
||||
import net.minecraft.server.v1_16_R3.Containers;
|
||||
import net.minecraft.server.v1_16_R3.Entity;
|
||||
import net.minecraft.server.v1_16_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_16_R3.MinecraftServer;
|
||||
import net.minecraft.server.v1_16_R3.PacketPlayOutOpenWindow;
|
||||
import net.minecraft.server.v1_16_R3.PlayerInteractManager;
|
||||
import net.minecraft.server.v1_16_R3.World;
|
||||
import net.minecraft.server.v1_16_R3.WorldServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.event.CraftEventFactory;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftContainer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PlayerDataManager implements IPlayerDataManager {
|
||||
|
||||
private @Nullable Field bukkitEntity;
|
||||
|
||||
public PlayerDataManager() {
|
||||
try {
|
||||
bukkitEntity = Entity.class.getDeclaredField("bukkitEntity");
|
||||
} catch (NoSuchFieldException e) {
|
||||
System.out.println("Unable to obtain field to inject custom save process - players' mounts may be deleted when loaded.");
|
||||
e.printStackTrace();
|
||||
bukkitEntity = null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static EntityPlayer getHandle(final Player player) {
|
||||
if (player instanceof CraftPlayer) {
|
||||
return ((CraftPlayer) player).getHandle();
|
||||
}
|
||||
|
||||
Server server = player.getServer();
|
||||
EntityPlayer nmsPlayer = null;
|
||||
|
||||
if (server instanceof CraftServer) {
|
||||
nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName());
|
||||
}
|
||||
|
||||
if (nmsPlayer == null) {
|
||||
// Could use reflection to examine fields, but it's honestly not worth the bother.
|
||||
throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation");
|
||||
}
|
||||
|
||||
return nmsPlayer;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Player loadPlayer(@NotNull final OfflinePlayer offline) {
|
||||
// Ensure player has data
|
||||
if (!offline.hasPlayedBefore()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a profile and entity to load the player data
|
||||
// See net.minecraft.server.PlayerList#attemptLogin
|
||||
GameProfile profile = new GameProfile(offline.getUniqueId(),
|
||||
offline.getName() != null ? offline.getName() : offline.getUniqueId().toString());
|
||||
MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||
WorldServer worldServer = server.getWorldServer(World.OVERWORLD);
|
||||
|
||||
if (worldServer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
EntityPlayer entity = new EntityPlayer(server, worldServer, profile, new PlayerInteractManager(worldServer));
|
||||
|
||||
try {
|
||||
injectPlayer(entity);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Get the bukkit entity
|
||||
Player target = entity.getBukkitEntity();
|
||||
if (target != null) {
|
||||
// Load data
|
||||
target.loadData();
|
||||
}
|
||||
// Return the entity
|
||||
return target;
|
||||
}
|
||||
|
||||
void injectPlayer(EntityPlayer player) throws IllegalAccessException {
|
||||
if (bukkitEntity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitEntity.setAccessible(true);
|
||||
|
||||
bukkitEntity.set(player, new OpenPlayer(player.server.server, player));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Player inject(@NotNull Player player) {
|
||||
try {
|
||||
EntityPlayer nmsPlayer = getHandle(player);
|
||||
injectPlayer(nmsPlayer);
|
||||
return nmsPlayer.getBukkitEntity();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) {
|
||||
|
||||
EntityPlayer nmsPlayer = getHandle(player);
|
||||
|
||||
if (nmsPlayer.playerConnection == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
InventoryView view = getView(player, inventory);
|
||||
|
||||
if (view == null) {
|
||||
return player.openInventory(inventory.getBukkitInventory());
|
||||
}
|
||||
|
||||
Container container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) {
|
||||
@Override
|
||||
public Containers<?> getType() {
|
||||
return getContainers(inventory.getBukkitInventory().getSize());
|
||||
}
|
||||
};
|
||||
|
||||
container.setTitle(new ChatComponentText(view.getTitle()));
|
||||
container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container);
|
||||
|
||||
if (container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
nmsPlayer.playerConnection.sendPacket(new PacketPlayOutOpenWindow(container.windowId, container.getType(),
|
||||
new ChatComponentText(container.getBukkitView().getTitle())));
|
||||
nmsPlayer.activeContainer = container;
|
||||
container.addSlotListener(nmsPlayer);
|
||||
|
||||
return container.getBukkitView();
|
||||
|
||||
}
|
||||
|
||||
private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) {
|
||||
if (inventory instanceof SpecialEnderChest) {
|
||||
return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest");
|
||||
} else if (inventory instanceof SpecialPlayerInventory) {
|
||||
return new OpenInventoryView(player, inventory, "container.player", "'s Inventory");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static @NotNull Containers<?> getContainers(int inventorySize) {
|
||||
switch (inventorySize) {
|
||||
case 9:
|
||||
return Containers.GENERIC_9X1;
|
||||
case 18:
|
||||
return Containers.GENERIC_9X2;
|
||||
case 36:
|
||||
return Containers.GENERIC_9X4;
|
||||
case 41: // PLAYER
|
||||
case 45:
|
||||
return Containers.GENERIC_9X5;
|
||||
case 54:
|
||||
return Containers.GENERIC_9X6;
|
||||
case 27:
|
||||
default:
|
||||
return Containers.GENERIC_9X3;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertToPlayerSlot(InventoryView view, int rawSlot) {
|
||||
int topSize = view.getTopInventory().getSize();
|
||||
if (topSize <= rawSlot) {
|
||||
// Slot is not inside special inventory, use Bukkit logic.
|
||||
return view.convertSlot(rawSlot);
|
||||
}
|
||||
|
||||
// Main inventory, slots 0-26 -> 9-35
|
||||
if (rawSlot < 27) {
|
||||
return rawSlot + 9;
|
||||
}
|
||||
// Hotbar, slots 27-35 -> 0-8
|
||||
if (rawSlot < 36) {
|
||||
return rawSlot - 27;
|
||||
}
|
||||
// Armor, slots 36-39 -> 39-36
|
||||
if (rawSlot < 40) {
|
||||
return 36 + (39 - rawSlot);
|
||||
}
|
||||
// Off hand
|
||||
if (rawSlot == 40) {
|
||||
return 40;
|
||||
}
|
||||
// Drop slots, "out of inventory"
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -14,25 +14,26 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.internal.v1_14_R1;
|
||||
package com.lishid.openinv.internal.v1_16_R3;
|
||||
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import java.util.List;
|
||||
import net.minecraft.server.v1_14_R1.AutoRecipeStackManager;
|
||||
import net.minecraft.server.v1_14_R1.ContainerUtil;
|
||||
import net.minecraft.server.v1_14_R1.EntityHuman;
|
||||
import net.minecraft.server.v1_14_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_14_R1.IInventoryListener;
|
||||
import net.minecraft.server.v1_14_R1.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_14_R1.ItemStack;
|
||||
import net.minecraft.server.v1_14_R1.NonNullList;
|
||||
import net.minecraft.server.v1_16_R3.AutoRecipeStackManager;
|
||||
import net.minecraft.server.v1_16_R3.ContainerUtil;
|
||||
import net.minecraft.server.v1_16_R3.EntityHuman;
|
||||
import net.minecraft.server.v1_16_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_16_R3.IInventoryListener;
|
||||
import net.minecraft.server.v1_16_R3.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_16_R3.ItemStack;
|
||||
import net.minecraft.server.v1_16_R3.NonNullList;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEnderChest {
|
||||
|
||||
|
@ -115,7 +116,7 @@ public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEn
|
|||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
public @Nullable Location getLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -131,7 +132,7 @@ public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEn
|
|||
|
||||
@Override
|
||||
public ItemStack getItem(int i) {
|
||||
return i >= 0 && i < this.items.size() ? this.items.get(i) : ItemStack.a;
|
||||
return i >= 0 && i < this.items.size() ? this.items.get(i) : ItemStack.b;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -153,7 +154,7 @@ public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEn
|
|||
if (itemstack2.isEmpty()) {
|
||||
this.setItem(i, itemstack1);
|
||||
this.update();
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
}
|
||||
|
||||
if (ItemStack.c(itemstack2, itemstack1)) {
|
||||
|
@ -164,7 +165,7 @@ public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEn
|
|||
itemstack1.subtract(k);
|
||||
if (itemstack1.isEmpty()) {
|
||||
this.update();
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -181,9 +182,9 @@ public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEn
|
|||
public ItemStack splitWithoutUpdate(int i) {
|
||||
ItemStack itemstack = this.items.get(i);
|
||||
if (itemstack.isEmpty()) {
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
} else {
|
||||
this.items.set(i, ItemStack.a);
|
||||
this.items.set(i, ItemStack.b);
|
||||
return itemstack;
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +205,7 @@ public class SpecialEnderChest extends InventoryEnderChest implements ISpecialEn
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotEmpty() {
|
||||
public boolean isEmpty() {
|
||||
|
||||
for (ItemStack itemstack : this.items) {
|
||||
if (!itemstack.isEmpty()) {
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.lishid.openinv.internal.v1_14_R1;
|
||||
package com.lishid.openinv.internal.v1_16_R3;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
|
@ -22,29 +22,31 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.server.v1_14_R1.AutoRecipeStackManager;
|
||||
import net.minecraft.server.v1_14_R1.ChatMessage;
|
||||
import net.minecraft.server.v1_14_R1.ContainerUtil;
|
||||
import net.minecraft.server.v1_14_R1.CrashReport;
|
||||
import net.minecraft.server.v1_14_R1.CrashReportSystemDetails;
|
||||
import net.minecraft.server.v1_14_R1.EntityHuman;
|
||||
import net.minecraft.server.v1_14_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_14_R1.EnumItemSlot;
|
||||
import net.minecraft.server.v1_14_R1.IBlockData;
|
||||
import net.minecraft.server.v1_14_R1.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_14_R1.Item;
|
||||
import net.minecraft.server.v1_14_R1.ItemArmor;
|
||||
import net.minecraft.server.v1_14_R1.ItemStack;
|
||||
import net.minecraft.server.v1_14_R1.NBTTagCompound;
|
||||
import net.minecraft.server.v1_14_R1.NBTTagList;
|
||||
import net.minecraft.server.v1_14_R1.NonNullList;
|
||||
import net.minecraft.server.v1_14_R1.PacketPlayOutSetSlot;
|
||||
import net.minecraft.server.v1_14_R1.PlayerInventory;
|
||||
import net.minecraft.server.v1_14_R1.ReportedException;
|
||||
import net.minecraft.server.v1_14_R1.World;
|
||||
import net.minecraft.server.v1_16_R3.AutoRecipeStackManager;
|
||||
import net.minecraft.server.v1_16_R3.ChatMessage;
|
||||
import net.minecraft.server.v1_16_R3.ContainerUtil;
|
||||
import net.minecraft.server.v1_16_R3.CrashReport;
|
||||
import net.minecraft.server.v1_16_R3.CrashReportSystemDetails;
|
||||
import net.minecraft.server.v1_16_R3.DamageSource;
|
||||
import net.minecraft.server.v1_16_R3.EntityHuman;
|
||||
import net.minecraft.server.v1_16_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_16_R3.EnumItemSlot;
|
||||
import net.minecraft.server.v1_16_R3.IBlockData;
|
||||
import net.minecraft.server.v1_16_R3.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_16_R3.IInventory;
|
||||
import net.minecraft.server.v1_16_R3.Item;
|
||||
import net.minecraft.server.v1_16_R3.ItemArmor;
|
||||
import net.minecraft.server.v1_16_R3.ItemStack;
|
||||
import net.minecraft.server.v1_16_R3.NBTTagCompound;
|
||||
import net.minecraft.server.v1_16_R3.NBTTagList;
|
||||
import net.minecraft.server.v1_16_R3.NonNullList;
|
||||
import net.minecraft.server.v1_16_R3.PacketPlayOutSetSlot;
|
||||
import net.minecraft.server.v1_16_R3.PlayerInventory;
|
||||
import net.minecraft.server.v1_16_R3.ReportedException;
|
||||
import net.minecraft.server.v1_16_R3.World;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftInventory;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftInventory;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
@ -57,7 +59,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
private boolean playerOnline;
|
||||
private EntityHuman player;
|
||||
private NonNullList<ItemStack> items, armor, extraSlots;
|
||||
private final List<NonNullList<ItemStack>> f;
|
||||
private List<NonNullList<ItemStack>> f;
|
||||
|
||||
public SpecialPlayerInventory(final Player bukkitPlayer, final Boolean online) {
|
||||
super(PlayerDataManager.getHandle(bukkitPlayer));
|
||||
|
@ -83,6 +85,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
this.items = this.player.inventory.items;
|
||||
this.armor = this.player.inventory.armor;
|
||||
this.extraSlots = this.player.inventory.extraSlots;
|
||||
this.f = ImmutableList.of(this.items, this.armor, this.extraSlots);
|
||||
this.playerOnline = true;
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +119,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
}
|
||||
|
||||
return list.get(i);
|
||||
|
@ -132,7 +135,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
i -= next.size();
|
||||
}
|
||||
|
||||
return list == null ? ItemStack.a : list.get(i);
|
||||
return list == null ? ItemStack.b : list.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -228,10 +231,10 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
}
|
||||
|
||||
return list.get(i).isEmpty() ? ItemStack.a : ContainerUtil.a(list, i, j);
|
||||
return list.get(i).isEmpty() ? ItemStack.b : ContainerUtil.a(list, i, j);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -253,17 +256,17 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
|
||||
if (i >= list.size()) {
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
}
|
||||
|
||||
if (!list.get(i).isEmpty()) {
|
||||
ItemStack itemstack = list.get(i);
|
||||
|
||||
list.set(i, ItemStack.a);
|
||||
list.set(i, ItemStack.b);
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
return ItemStack.a;
|
||||
return ItemStack.b;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -303,10 +306,10 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
|
||||
@Override
|
||||
public ItemStack getItemInHand() {
|
||||
return d(this.itemInHandIndex) ? this.items.get(this.itemInHandIndex) : ItemStack.a;
|
||||
return d(this.itemInHandIndex) ? this.items.get(this.itemInHandIndex) : ItemStack.b;
|
||||
}
|
||||
|
||||
private boolean a(ItemStack itemstack, ItemStack itemstack1) {
|
||||
private boolean isSimilarAndNotFull(ItemStack itemstack, ItemStack itemstack1) {
|
||||
return !itemstack.isEmpty() && this.b(itemstack, itemstack1) && itemstack.isStackable() && itemstack.getCount() < itemstack.getMaxStackSize() && itemstack.getCount() < this.getMaxStackSize();
|
||||
}
|
||||
|
||||
|
@ -324,8 +327,8 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
return itemstack.getCount();
|
||||
}
|
||||
|
||||
if (!this.a(itemstack, itemstack1)) {
|
||||
remains -= (itemstack1.getMaxStackSize() < this.getMaxStackSize() ? itemstack1.getMaxStackSize() : this.getMaxStackSize()) - itemstack1.getCount();
|
||||
if (!this.isSimilarAndNotFull(itemstack, itemstack1)) {
|
||||
remains -= Math.min(itemstack1.getMaxStackSize(), this.getMaxStackSize()) - itemstack1.getCount();
|
||||
}
|
||||
|
||||
if (remains <= 0) {
|
||||
|
@ -333,6 +336,11 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
}
|
||||
|
||||
ItemStack offhandItemStack = this.getItem(this.items.size() + this.armor.size());
|
||||
if (this.isSimilarAndNotFull(offhandItemStack, itemstack)) {
|
||||
remains -= Math.min(offhandItemStack.getMaxStackSize(), this.getMaxStackSize()) - offhandItemStack.getCount();
|
||||
}
|
||||
|
||||
return itemstack.getCount() - remains;
|
||||
}
|
||||
|
||||
|
@ -389,41 +397,14 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
|
||||
@Override
|
||||
public int a(Predicate<ItemStack> predicate, int i) {
|
||||
int j = 0;
|
||||
|
||||
int k;
|
||||
for (k = 0; k < this.getSize(); ++k) {
|
||||
ItemStack itemstack = this.getItem(k);
|
||||
if (!itemstack.isEmpty() && predicate.test(itemstack)) {
|
||||
int l = i <= 0 ? itemstack.getCount() : Math.min(i - j, itemstack.getCount());
|
||||
j += l;
|
||||
if (i != 0) {
|
||||
itemstack.subtract(l);
|
||||
if (itemstack.isEmpty()) {
|
||||
this.setItem(k, ItemStack.a);
|
||||
}
|
||||
|
||||
if (i > 0 && j >= i) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.getCarried().isEmpty() && predicate.test(this.getCarried())) {
|
||||
k = i <= 0 ? this.getCarried().getCount() : Math.min(i - j, this.getCarried().getCount());
|
||||
j += k;
|
||||
if (i != 0) {
|
||||
this.getCarried().subtract(k);
|
||||
if (this.getCarried().isEmpty()) {
|
||||
this.setCarried(ItemStack.a);
|
||||
}
|
||||
|
||||
if (i > 0 && j >= i) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
public int a(Predicate<ItemStack> predicate, int i, IInventory iinventory) {
|
||||
byte b0 = 0;
|
||||
boolean flag = i == 0;
|
||||
int j = b0 + ContainerUtil.a(this, predicate, i - b0, flag);
|
||||
j += ContainerUtil.a(iinventory, predicate, i - j, flag);
|
||||
j += ContainerUtil.a(this.getCarried(), predicate, i - j, flag);
|
||||
if (this.getCarried().isEmpty()) {
|
||||
this.setCarried(ItemStack.b);
|
||||
}
|
||||
|
||||
return j;
|
||||
|
@ -444,8 +425,9 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
ItemStack itemstack1 = this.getItem(i);
|
||||
if (itemstack1.isEmpty()) {
|
||||
itemstack1 = new ItemStack(item, 0);
|
||||
if (itemstack.hasTag()) {
|
||||
itemstack1.setTag(itemstack.getTag().clone());
|
||||
NBTTagCompound tag = itemstack.getTag();
|
||||
if (tag != null) {
|
||||
itemstack1.setTag(tag.clone());
|
||||
}
|
||||
|
||||
this.setItem(i, itemstack1);
|
||||
|
@ -460,25 +442,23 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
k = this.getMaxStackSize() - itemstack1.getCount();
|
||||
}
|
||||
|
||||
if (k == 0) {
|
||||
return j;
|
||||
} else {
|
||||
if (k != 0) {
|
||||
j -= k;
|
||||
itemstack1.add(k);
|
||||
itemstack1.d(5);
|
||||
return j;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int firstPartial(ItemStack itemstack) {
|
||||
if (this.a(this.getItem(this.itemInHandIndex), itemstack)) {
|
||||
if (this.isSimilarAndNotFull(this.getItem(this.itemInHandIndex), itemstack)) {
|
||||
return this.itemInHandIndex;
|
||||
} else if (this.a(this.getItem(40), itemstack)) {
|
||||
} else if (this.isSimilarAndNotFull(this.getItem(40), itemstack)) {
|
||||
return 40;
|
||||
} else {
|
||||
for (int i = 0; i < this.items.size(); ++i) {
|
||||
if (this.a(this.items.get(i), itemstack)) {
|
||||
if (this.isSimilarAndNotFull(this.items.get(i), itemstack)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -585,7 +565,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
for (List<ItemStack> list : this.f) {
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
if (list.get(i) == itemstack) {
|
||||
list.set(i, ItemStack.a);
|
||||
list.set(i, ItemStack.b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -655,12 +635,12 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean isNotEmpty() {
|
||||
Iterator iterator = this.items.iterator();
|
||||
public boolean isEmpty() {
|
||||
Iterator<ItemStack> iterator = this.items.iterator();
|
||||
|
||||
ItemStack itemstack;
|
||||
while (iterator.hasNext()) {
|
||||
itemstack = (ItemStack)iterator.next();
|
||||
itemstack = iterator.next();
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -669,7 +649,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
iterator = this.armor.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
itemstack = (ItemStack)iterator.next();
|
||||
itemstack = iterator.next();
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -678,7 +658,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
iterator = this.extraSlots.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
itemstack = (ItemStack)iterator.next();
|
||||
itemstack = iterator.next();
|
||||
if (!itemstack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -694,12 +674,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean b(IBlockData iblockdata) {
|
||||
return this.getItem(this.itemInHandIndex).b(iblockdata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void a(float f) {
|
||||
public void a(DamageSource damagesource, float f) {
|
||||
if (f > 0.0F) {
|
||||
f /= 4.0F;
|
||||
if (f < 1.0F) {
|
||||
|
@ -709,8 +684,8 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
for (int i = 0; i < this.armor.size(); ++i) {
|
||||
ItemStack itemstack = this.armor.get(0);
|
||||
int index = i;
|
||||
if (itemstack.getItem() instanceof ItemArmor) {
|
||||
itemstack.damage((int) f, this.player, (entityhuman) -> entityhuman.c(EnumItemSlot.a(EnumItemSlot.Function.ARMOR, index)));
|
||||
if ((!damagesource.isFire() || !itemstack.getItem().u()) && itemstack.getItem() instanceof ItemArmor) {
|
||||
itemstack.damage((int) f, this.player, (entityHuman) -> entityHuman.broadcastItemBreak(EnumItemSlot.a(EnumItemSlot.Function.ARMOR, index)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -722,7 +697,7 @@ public class SpecialPlayerInventory extends PlayerInventory implements ISpecialP
|
|||
for (int i = 0; i < itemStacks.size(); ++i) {
|
||||
ItemStack itemstack = itemStacks.get(i);
|
||||
if (!itemstack.isEmpty()) {
|
||||
itemStacks.set(i, ItemStack.a);
|
||||
itemStacks.set(i, ItemStack.b);
|
||||
this.player.a(itemstack, true, false);
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 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/>.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvinternal</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvadapter1_8_R3</artifactId>
|
||||
<name>OpenInvAdapter1_8_R3</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvcommon</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,248 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_8_R3;
|
||||
|
||||
import com.lishid.openinv.internal.IAnySilentContainer;
|
||||
import java.lang.reflect.Field;
|
||||
import net.minecraft.server.v1_8_R3.AxisAlignedBB;
|
||||
import net.minecraft.server.v1_8_R3.Block;
|
||||
import net.minecraft.server.v1_8_R3.BlockChest;
|
||||
import net.minecraft.server.v1_8_R3.BlockEnderChest;
|
||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R3.Entity;
|
||||
import net.minecraft.server.v1_8_R3.EntityOcelot;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.EnumDirection;
|
||||
import net.minecraft.server.v1_8_R3.ITileInventory;
|
||||
import net.minecraft.server.v1_8_R3.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_8_R3.InventoryLargeChest;
|
||||
import net.minecraft.server.v1_8_R3.PlayerInteractManager;
|
||||
import net.minecraft.server.v1_8_R3.StatisticList;
|
||||
import net.minecraft.server.v1_8_R3.TileEntity;
|
||||
import net.minecraft.server.v1_8_R3.TileEntityChest;
|
||||
import net.minecraft.server.v1_8_R3.TileEntityEnderChest;
|
||||
import net.minecraft.server.v1_8_R3.World;
|
||||
import net.minecraft.server.v1_8_R3.WorldSettings.EnumGamemode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AnySilentContainer implements IAnySilentContainer {
|
||||
|
||||
private Field playerInteractManagerGamemode;
|
||||
|
||||
public AnySilentContainer() {
|
||||
try {
|
||||
this.playerInteractManagerGamemode = PlayerInteractManager.class.getDeclaredField("gamemode");
|
||||
this.playerInteractManagerGamemode.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
System.err.println("[OpenInv] Unable to directly write player gamemode! SilentChest will fail.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnySilentContainer(@NotNull org.bukkit.block.Block bukkitBlock) {
|
||||
return bukkitBlock.getType() == Material.ENDER_CHEST || bukkitBlock.getState() instanceof org.bukkit.block.Chest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnyContainerNeeded(@NotNull Player bukkitPlayer, @NotNull org.bukkit.block.Block bukkitBlock) {
|
||||
|
||||
World world = PlayerDataManager.getHandle(bukkitPlayer).world;
|
||||
BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ());
|
||||
Block block = world.getType(blockPosition).getBlock();
|
||||
|
||||
if (block instanceof BlockEnderChest) {
|
||||
// Ender chests are not blocked by ocelots.
|
||||
return world.getType(blockPosition.up()).getBlock().c();
|
||||
}
|
||||
|
||||
// Check if chest is blocked or has an ocelot on top
|
||||
if (isBlockedChest(world, blockPosition)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for matching adjacent chests that are blocked or have an ocelot on top
|
||||
for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) {
|
||||
BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection);
|
||||
Block localBlock = world.getType(localBlockPosition).getBlock();
|
||||
|
||||
if (localBlock != block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TileEntity localTileEntity = world.getTileEntity(localBlockPosition);
|
||||
if (!(localTileEntity instanceof TileEntityChest)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isBlockedChest(world, localBlockPosition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBlockedChest(World world, BlockPosition blockPosition) {
|
||||
// For reference, loot at net.minecraft.server.BlockChest
|
||||
return world.getType(blockPosition.up()).getBlock().c() || hasOcelotOnTop(world, blockPosition);
|
||||
}
|
||||
|
||||
private boolean hasOcelotOnTop(World world, BlockPosition blockPosition) {
|
||||
for (Entity localEntity : world.a(EntityOcelot.class,
|
||||
new AxisAlignedBB(blockPosition.getX(), blockPosition.getY() + 1,
|
||||
blockPosition.getZ(), blockPosition.getX() + 1, blockPosition.getY() + 2,
|
||||
blockPosition.getZ() + 1))) {
|
||||
EntityOcelot localEntityOcelot = (EntityOcelot) localEntity;
|
||||
if (localEntityOcelot.isSitting()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activateContainer(@NotNull Player bukkitPlayer, boolean silent, @NotNull org.bukkit.block.Block bukkitBlock) {
|
||||
|
||||
EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer);
|
||||
|
||||
// Silent ender chest is pretty much API-only
|
||||
if (silent && bukkitBlock.getType() == Material.ENDER_CHEST) {
|
||||
bukkitPlayer.openInventory(bukkitPlayer.getEnderChest());
|
||||
player.b(StatisticList.V);
|
||||
return true;
|
||||
}
|
||||
|
||||
World world = player.world;
|
||||
BlockPosition blockPosition = new BlockPosition(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ());
|
||||
Object tile = world.getTileEntity(blockPosition);
|
||||
|
||||
if (tile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tile instanceof TileEntityEnderChest) {
|
||||
// Anychest ender chest. See net.minecraft.server.BlockEnderChest
|
||||
InventoryEnderChest enderChest = player.getEnderChest();
|
||||
enderChest.a((TileEntityEnderChest) tile);
|
||||
player.openContainer(enderChest);
|
||||
player.b(StatisticList.V);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(tile instanceof ITileInventory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ITileInventory tileInventory = (ITileInventory) tile;
|
||||
Block block = world.getType(blockPosition).getBlock();
|
||||
|
||||
if (block instanceof BlockChest) {
|
||||
for (EnumDirection localEnumDirection : EnumDirection.EnumDirectionLimit.HORIZONTAL) {
|
||||
BlockPosition localBlockPosition = blockPosition.shift(localEnumDirection);
|
||||
Block localBlock = world.getType(localBlockPosition).getBlock();
|
||||
|
||||
if (localBlock != block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TileEntity localTileEntity = world.getTileEntity(localBlockPosition);
|
||||
if (!(localTileEntity instanceof TileEntityChest)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((localEnumDirection == EnumDirection.WEST) || (localEnumDirection == EnumDirection.NORTH)) {
|
||||
tileInventory = new InventoryLargeChest("container.chestDouble",
|
||||
(TileEntityChest) localTileEntity, tileInventory);
|
||||
} else {
|
||||
tileInventory = new InventoryLargeChest("container.chestDouble",
|
||||
tileInventory, (TileEntityChest) localTileEntity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
BlockChest blockChest = (BlockChest) block;
|
||||
if (blockChest.b == 0) {
|
||||
player.b(StatisticList.aa);
|
||||
} else if (blockChest.b == 1) {
|
||||
player.b(StatisticList.U);
|
||||
}
|
||||
}
|
||||
|
||||
// AnyChest only - SilentChest not active, container unsupported, or unnecessary.
|
||||
if (!silent || player.playerInteractManager.getGameMode() == EnumGamemode.SPECTATOR) {
|
||||
player.openContainer(tileInventory);
|
||||
return true;
|
||||
}
|
||||
|
||||
// SilentChest requires access to setting players' gamemode directly.
|
||||
if (this.playerInteractManagerGamemode == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumGamemode gamemode = player.playerInteractManager.getGameMode();
|
||||
this.forceGameMode(player, EnumGamemode.SPECTATOR);
|
||||
player.openContainer(tileInventory);
|
||||
this.forceGameMode(player, gamemode);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivateContainer(@NotNull final Player bukkitPlayer) {
|
||||
if (this.playerInteractManagerGamemode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryView view = bukkitPlayer.getOpenInventory();
|
||||
switch (view.getType()) {
|
||||
case CHEST:
|
||||
case ENDER_CHEST:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
EntityPlayer player = PlayerDataManager.getHandle(bukkitPlayer);
|
||||
|
||||
EnumGamemode gamemode = player.playerInteractManager.getGameMode();
|
||||
this.forceGameMode(player, EnumGamemode.SPECTATOR);
|
||||
player.activeContainer.b(player);
|
||||
player.activeContainer = player.defaultContainer;
|
||||
this.forceGameMode(player, gamemode);
|
||||
}
|
||||
|
||||
private void forceGameMode(final EntityPlayer player, final EnumGamemode gameMode) {
|
||||
if (this.playerInteractManagerGamemode == null) {
|
||||
// No need to warn repeatedly, error on startup and lack of function should be enough.
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!this.playerInteractManagerGamemode.isAccessible()) {
|
||||
// Just in case, ensure accessible.
|
||||
this.playerInteractManagerGamemode.setAccessible(true);
|
||||
}
|
||||
this.playerInteractManagerGamemode.set(player.playerInteractManager, gameMode);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_8_R3;
|
||||
|
||||
import com.lishid.openinv.internal.IPlayerDataManager;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
||||
import net.minecraft.server.v1_8_R3.PlayerInteractManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PlayerDataManager implements IPlayerDataManager {
|
||||
|
||||
@Override
|
||||
public Player loadPlayer(@NotNull OfflinePlayer offline) {
|
||||
// Ensure the player has data
|
||||
if (!offline.hasPlayedBefore()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a profile and entity to load the player data
|
||||
GameProfile profile = new GameProfile(offline.getUniqueId(), offline.getName());
|
||||
MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
|
||||
EntityPlayer entity = new EntityPlayer(server, server.getWorldServer(0), profile,
|
||||
new PlayerInteractManager(server.getWorldServer(0)));
|
||||
|
||||
// Get the bukkit entity
|
||||
Player target = entity.getBukkitEntity();
|
||||
if (target != null) {
|
||||
// Load data
|
||||
target.loadData();
|
||||
}
|
||||
// Return the entity
|
||||
return target;
|
||||
}
|
||||
|
||||
public static EntityPlayer getHandle(Player player) {
|
||||
if (player instanceof CraftPlayer) {
|
||||
return ((CraftPlayer) player).getHandle();
|
||||
}
|
||||
|
||||
Server server = player.getServer();
|
||||
EntityPlayer nmsPlayer = null;
|
||||
|
||||
if (server instanceof CraftServer) {
|
||||
nmsPlayer = ((CraftServer) server).getHandle().getPlayer(player.getName());
|
||||
}
|
||||
|
||||
if (nmsPlayer == null) {
|
||||
// Could use reflection to examine fields, but it's honestly not worth the bother.
|
||||
throw new RuntimeException("Unable to fetch EntityPlayer from provided Player implementation");
|
||||
}
|
||||
|
||||
return nmsPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) {
|
||||
return player.openInventory(inventory.getBukkitInventory());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_8_R3;
|
||||
|
||||
import com.lishid.openinv.internal.ISpecialEnderChest;
|
||||
import java.lang.reflect.Field;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.IInventory;
|
||||
import net.minecraft.server.v1_8_R3.InventoryEnderChest;
|
||||
import net.minecraft.server.v1_8_R3.InventorySubcontainer;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SpecialEnderChest extends InventorySubcontainer implements IInventory, ISpecialEnderChest {
|
||||
|
||||
private final InventoryEnderChest enderChest;
|
||||
private final CraftInventory inventory = new CraftInventory(this);
|
||||
private boolean playerOnline;
|
||||
|
||||
public SpecialEnderChest(Player player, Boolean online) {
|
||||
super(PlayerDataManager.getHandle(player).getEnderChest().getName(),
|
||||
PlayerDataManager.getHandle(player).getEnderChest().hasCustomName(),
|
||||
PlayerDataManager.getHandle(player).getEnderChest().getSize());
|
||||
this.playerOnline = online;
|
||||
EntityPlayer nmsPlayer = PlayerDataManager.getHandle(player);
|
||||
this.enderChest = nmsPlayer.getEnderChest();
|
||||
this.bukkitOwner = nmsPlayer.getBukkitEntity();
|
||||
this.items = enderChest.getContents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getBukkitInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOnline(@NotNull Player player) {
|
||||
if (!playerOnline) {
|
||||
try {
|
||||
EntityPlayer nmsPlayer = PlayerDataManager.getHandle(player);
|
||||
this.bukkitOwner = nmsPlayer.getBukkitEntity();
|
||||
InventoryEnderChest playerEnderChest = nmsPlayer.getEnderChest();
|
||||
Field field = playerEnderChest.getClass().getField("items");
|
||||
field.setAccessible(true);
|
||||
field.set(playerEnderChest, this.items);
|
||||
} catch (Exception ignored) {}
|
||||
playerOnline = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOffline() {
|
||||
playerOnline = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUse() {
|
||||
return !this.getViewers().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
enderChest.update();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.internal.v1_8_R3;
|
||||
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import net.minecraft.server.v1_8_R3.ItemStack;
|
||||
import net.minecraft.server.v1_8_R3.PlayerInventory;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SpecialPlayerInventory extends PlayerInventory implements ISpecialPlayerInventory {
|
||||
|
||||
private final ItemStack[] extra = new ItemStack[5];
|
||||
private final CraftInventory inventory = new CraftInventory(this);
|
||||
private boolean playerOnline;
|
||||
|
||||
public SpecialPlayerInventory(Player bukkitPlayer, Boolean online) {
|
||||
super(PlayerDataManager.getHandle(bukkitPlayer));
|
||||
this.playerOnline = online;
|
||||
this.items = player.inventory.items;
|
||||
this.armor = player.inventory.armor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getBukkitInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOnline(@NotNull Player player) {
|
||||
if (!playerOnline) {
|
||||
this.player = PlayerDataManager.getHandle(player);
|
||||
this.player.inventory.items = this.items;
|
||||
this.player.inventory.armor = this.armor;
|
||||
playerOnline = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerOffline() {
|
||||
playerOnline = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUse() {
|
||||
return !this.getViewers().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getContents() {
|
||||
ItemStack[] contents = new ItemStack[getSize()];
|
||||
System.arraycopy(items, 0, contents, 0, items.length);
|
||||
System.arraycopy(armor, 0, contents, items.length, armor.length);
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return super.getSize() + 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int i) {
|
||||
ItemStack[] is = this.items;
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.armor;
|
||||
} else {
|
||||
i = getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.extra;
|
||||
} else if (is == this.armor) {
|
||||
i = getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
return is[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack splitStack(int i, int j) {
|
||||
ItemStack[] is = this.items;
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.armor;
|
||||
} else {
|
||||
i = getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.extra;
|
||||
} else if (is == this.armor) {
|
||||
i = getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
if (is[i] != null) {
|
||||
ItemStack itemstack;
|
||||
|
||||
if (is[i].count <= j) {
|
||||
itemstack = is[i];
|
||||
is[i] = null;
|
||||
return itemstack;
|
||||
} else {
|
||||
itemstack = is[i].cloneAndSubtract(j);
|
||||
if (is[i].count == 0) {
|
||||
is[i] = null;
|
||||
}
|
||||
|
||||
return itemstack;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack splitWithoutUpdate(int i) {
|
||||
ItemStack[] is = this.items;
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.armor;
|
||||
} else {
|
||||
i = getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.extra;
|
||||
} else if (is == this.armor) {
|
||||
i = getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
if (is[i] != null) {
|
||||
ItemStack itemstack = is[i];
|
||||
|
||||
is[i] = null;
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int i, ItemStack itemstack) {
|
||||
ItemStack[] is = this.items;
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.armor;
|
||||
} else {
|
||||
i = getReversedItemSlotNum(i);
|
||||
}
|
||||
|
||||
if (i >= is.length) {
|
||||
i -= is.length;
|
||||
is = this.extra;
|
||||
} else if (is == this.armor) {
|
||||
i = getReversedArmorSlotNum(i);
|
||||
}
|
||||
|
||||
// Effects
|
||||
if (is == this.extra) {
|
||||
player.drop(itemstack, true);
|
||||
itemstack = null;
|
||||
}
|
||||
|
||||
is[i] = itemstack;
|
||||
|
||||
player.defaultContainer.b();
|
||||
}
|
||||
|
||||
private int getReversedItemSlotNum(int i) {
|
||||
if (i >= 27) {
|
||||
return i - 27;
|
||||
}
|
||||
return i + 9;
|
||||
}
|
||||
|
||||
private int getReversedArmorSlotNum(int i) {
|
||||
if (i == 0) {
|
||||
return 3;
|
||||
}
|
||||
if (i == 1) {
|
||||
return 2;
|
||||
}
|
||||
if (i == 2) {
|
||||
return 1;
|
||||
}
|
||||
if (i == 3) {
|
||||
return 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (player.getName().length() > 16) {
|
||||
return player.getName().substring(0, 16);
|
||||
}
|
||||
return player.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCustomName() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2019 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
@ -21,7 +21,7 @@
|
|||
<parent>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvparent</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.5-TF</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>openinvplugincore</artifactId>
|
||||
|
@ -30,13 +30,13 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lishid</groupId>
|
||||
<artifactId>openinvcommon</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<artifactId>openinvapi</artifactId>
|
||||
<version>4.1.5-TF</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||
<version>1.15.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -52,7 +52,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -18,24 +18,22 @@ package com.lishid.openinv;
|
|||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.lishid.openinv.commands.AnyChestPluginCommand;
|
||||
import com.lishid.openinv.commands.OpenInvPluginCommand;
|
||||
import com.lishid.openinv.commands.SearchEnchantPluginCommand;
|
||||
import com.lishid.openinv.commands.SearchInvPluginCommand;
|
||||
import com.lishid.openinv.commands.SilentChestPluginCommand;
|
||||
import com.lishid.openinv.commands.ContainerSettingCommand;
|
||||
import com.lishid.openinv.commands.OpenInvCommand;
|
||||
import com.lishid.openinv.commands.SearchContainerCommand;
|
||||
import com.lishid.openinv.commands.SearchEnchantCommand;
|
||||
import com.lishid.openinv.commands.SearchInvCommand;
|
||||
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.listeners.InventoryClickListener;
|
||||
import com.lishid.openinv.listeners.InventoryCloseListener;
|
||||
import com.lishid.openinv.listeners.InventoryDragListener;
|
||||
import com.lishid.openinv.listeners.InventoryListener;
|
||||
import com.lishid.openinv.listeners.PlayerListener;
|
||||
import com.lishid.openinv.listeners.PluginListener;
|
||||
import com.lishid.openinv.util.Cache;
|
||||
import com.lishid.openinv.util.ConfigUpdater;
|
||||
import com.lishid.openinv.util.Function;
|
||||
import com.lishid.openinv.util.InternalAccessor;
|
||||
import com.lishid.openinv.util.LanguageManager;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -43,9 +41,13 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
|
@ -71,49 +73,43 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
private final Multimap<String, Class<? extends Plugin>> pluginUsage = HashMultimap.create();
|
||||
|
||||
private final Cache<String, Player> playerCache = new Cache<>(300000L,
|
||||
new Function<Player>() {
|
||||
@Override
|
||||
public boolean run(final Player value) {
|
||||
value -> {
|
||||
String key = OpenInv.this.getPlayerID(value);
|
||||
|
||||
String key = OpenInv.this.getPlayerID(value);
|
||||
return OpenInv.this.inventories.containsKey(key)
|
||||
&& OpenInv.this.inventories.get(key).isInUse()
|
||||
|| OpenInv.this.enderChests.containsKey(key)
|
||||
&& OpenInv.this.enderChests.get(key).isInUse()
|
||||
|| OpenInv.this.pluginUsage.containsKey(key);
|
||||
return OpenInv.this.inventories.containsKey(key)
|
||||
&& OpenInv.this.inventories.get(key).isInUse()
|
||||
|| OpenInv.this.enderChests.containsKey(key)
|
||||
&& OpenInv.this.enderChests.get(key).isInUse()
|
||||
|| OpenInv.this.pluginUsage.containsKey(key);
|
||||
},
|
||||
value -> {
|
||||
String key = OpenInv.this.getPlayerID(value);
|
||||
|
||||
// Check if inventory is stored, and if it is, remove it and eject all viewers
|
||||
if (OpenInv.this.inventories.containsKey(key)) {
|
||||
Inventory inv = OpenInv.this.inventories.remove(key).getBukkitInventory();
|
||||
List<HumanEntity> viewers = inv.getViewers();
|
||||
for (HumanEntity entity : viewers.toArray(new HumanEntity[0])) {
|
||||
entity.closeInventory();
|
||||
}
|
||||
}
|
||||
}, new Function<Player>() {
|
||||
@Override
|
||||
public boolean run(final Player value) {
|
||||
|
||||
String key = OpenInv.this.getPlayerID(value);
|
||||
|
||||
// Check if inventory is stored, and if it is, remove it and eject all viewers
|
||||
if (OpenInv.this.inventories.containsKey(key)) {
|
||||
Inventory inv = OpenInv.this.inventories.remove(key).getBukkitInventory();
|
||||
List<HumanEntity> viewers = inv.getViewers();
|
||||
for (HumanEntity entity : viewers.toArray(new HumanEntity[0])) {
|
||||
entity.closeInventory();
|
||||
// Check if ender chest is stored, and if it is, remove it and eject all viewers
|
||||
if (OpenInv.this.enderChests.containsKey(key)) {
|
||||
Inventory inv = OpenInv.this.enderChests.remove(key).getBukkitInventory();
|
||||
List<HumanEntity> viewers = inv.getViewers();
|
||||
for (HumanEntity entity : viewers.toArray(new HumanEntity[0])) {
|
||||
entity.closeInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if ender chest is stored, and if it is, remove it and eject all viewers
|
||||
if (OpenInv.this.enderChests.containsKey(key)) {
|
||||
Inventory inv = OpenInv.this.enderChests.remove(key).getBukkitInventory();
|
||||
List<HumanEntity> viewers = inv.getViewers();
|
||||
for (HumanEntity entity : viewers.toArray(new HumanEntity[0])) {
|
||||
entity.closeInventory();
|
||||
if (!OpenInv.this.disableSaving() && !value.isOnline()) {
|
||||
value.saveData();
|
||||
}
|
||||
}
|
||||
|
||||
if (!OpenInv.this.disableSaving() && !value.isOnline()) {
|
||||
value.saveData();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
private InternalAccessor accessor;
|
||||
private LanguageManager languageManager;
|
||||
|
||||
/**
|
||||
* Evicts all viewers lacking cross-world permissions from a Player's inventory.
|
||||
|
@ -131,12 +127,12 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
|
||||
if (this.inventories.containsKey(key)) {
|
||||
Iterator<HumanEntity> iterator = this.inventories.get(key).getBukkitInventory().getViewers().iterator();
|
||||
//noinspection WhileLoopReplaceableByForEach
|
||||
while (iterator.hasNext()) {
|
||||
HumanEntity human = iterator.next();
|
||||
// If player has permission or is in the same world, allow continued access
|
||||
// Just in case, also allow null worlds.
|
||||
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld() == null
|
||||
|| human.getWorld().equals(player.getWorld())) {
|
||||
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld().equals(player.getWorld())) {
|
||||
continue;
|
||||
}
|
||||
human.closeInventory();
|
||||
|
@ -145,10 +141,10 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
|
||||
if (this.enderChests.containsKey(key)) {
|
||||
Iterator<HumanEntity> iterator = this.enderChests.get(key).getBukkitInventory().getViewers().iterator();
|
||||
//noinspection WhileLoopReplaceableByForEach
|
||||
while (iterator.hasNext()) {
|
||||
HumanEntity human = iterator.next();
|
||||
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld() == null
|
||||
|| human.getWorld().equals(player.getWorld())) {
|
||||
if (Permissions.CROSSWORLD.hasPermission(human) || human.getWorld().equals(player.getWorld())) {
|
||||
continue;
|
||||
}
|
||||
human.closeInventory();
|
||||
|
@ -156,6 +152,20 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a raw slot number into a player inventory slot number.
|
||||
*
|
||||
* <p>Note that this method is specifically for converting an ISpecialPlayerInventory slot number into a regular
|
||||
* player inventory slot number.
|
||||
*
|
||||
* @param view the open inventory view
|
||||
* @param rawSlot the raw slot in the view
|
||||
* @return the converted slot number
|
||||
*/
|
||||
public int convertToPlayerSlot(InventoryView view, int rawSlot) {
|
||||
return this.accessor.getPlayerDataManager().convertToPlayerSlot(view, rawSlot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableSaving() {
|
||||
return this.getConfig().getBoolean("settings.disable-saving", false);
|
||||
|
@ -167,50 +177,6 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
return this.accessor.getAnySilentContainer();
|
||||
}
|
||||
|
||||
private int getLevenshteinDistance(final String string1, final String string2) {
|
||||
if (string1 == null || string2 == null) {
|
||||
throw new IllegalArgumentException("Strings must not be null");
|
||||
}
|
||||
|
||||
if (string1.isEmpty()) {
|
||||
return string2.length();
|
||||
}
|
||||
if (string2.isEmpty()) {
|
||||
return string2.length();
|
||||
}
|
||||
if (string1.equals(string2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len1 = string1.length();
|
||||
int len2 = string2.length();
|
||||
|
||||
int[] prevDistances = new int[len1 + 1];
|
||||
int[] distances = new int[len1 + 1];
|
||||
|
||||
for (int i = 0; i <= len1; ++i) {
|
||||
prevDistances[i] = i;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= len2; ++i) {
|
||||
// TODO: include tweaks available in Simmetrics?
|
||||
char string2char = string2.charAt(i - 1);
|
||||
distances[0] = i;
|
||||
|
||||
for (int j = 1; j <= len1; ++j) {
|
||||
int cost = string1.charAt(j - 1) == string2char ? 0 : 1;
|
||||
|
||||
distances[j] = Math.min(Math.min(distances[j - 1] + 1, prevDistances[j] + 1), prevDistances[j - 1] + cost);
|
||||
}
|
||||
|
||||
int[] swap = prevDistances;
|
||||
prevDistances = distances;
|
||||
distances = swap;
|
||||
}
|
||||
|
||||
return prevDistances[len1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPlayerAnyChestStatus(@NotNull final OfflinePlayer player) {
|
||||
boolean defaultState = false;
|
||||
|
@ -272,22 +238,18 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
return this.accessor != null && this.accessor.isSupported();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Player loadPlayer(@NotNull final OfflinePlayer offline) {
|
||||
public @Nullable Player loadPlayer(@NotNull final OfflinePlayer offline) {
|
||||
|
||||
String key = this.getPlayerID(offline);
|
||||
if (this.playerCache.containsKey(key)) {
|
||||
return this.playerCache.get(key);
|
||||
}
|
||||
|
||||
// TODO: wrap Player to ensure all methods can safely be called offline
|
||||
Player loaded;
|
||||
|
||||
if (offline.isOnline()) {
|
||||
loaded = offline.getPlayer();
|
||||
this.playerCache.put(key, loaded);
|
||||
return loaded;
|
||||
Player player = offline.getPlayer();
|
||||
if (player != null) {
|
||||
this.playerCache.put(key, player);
|
||||
return player;
|
||||
}
|
||||
|
||||
if (!this.isSupportedVersion()) {
|
||||
|
@ -301,33 +263,18 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
Future<Player> future = Bukkit.getScheduler().callSyncMethod(this,
|
||||
() -> OpenInv.this.accessor.getPlayerDataManager().loadPlayer(offline));
|
||||
|
||||
int ticks = 0;
|
||||
while (!future.isDone() && !future.isCancelled() && ticks < 10) {
|
||||
++ticks;
|
||||
try {
|
||||
Thread.sleep(50L);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!future.isDone() || future.isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
loaded = future.get();
|
||||
player = future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (loaded != null) {
|
||||
this.playerCache.put(key, loaded);
|
||||
if (player != null) {
|
||||
this.playerCache.put(key, player);
|
||||
}
|
||||
|
||||
return loaded;
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -335,6 +282,58 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
return this.accessor.getPlayerDataManager().openInventory(player, inventory);
|
||||
}
|
||||
|
||||
public void sendMessage(@NotNull CommandSender sender, @NotNull String key) {
|
||||
String message = this.languageManager.getValue(key, getLocale(sender));
|
||||
|
||||
if (message != null && !message.isEmpty()) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessage(@NotNull CommandSender sender, @NotNull String key, String... replacements) {
|
||||
String message = this.languageManager.getValue(key, getLocale(sender), replacements);
|
||||
|
||||
if (message != null && !message.isEmpty()) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSystemMessage(@NotNull Player player, @NotNull String key) {
|
||||
String message = this.languageManager.getValue(key, getLocale(player));
|
||||
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int newline = message.indexOf('\n');
|
||||
if (newline != -1) {
|
||||
// No newlines in action bar chat.
|
||||
message = message.substring(0, newline);
|
||||
}
|
||||
|
||||
if (message.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
|
||||
}
|
||||
|
||||
public @Nullable String getLocalizedMessage(@NotNull CommandSender sender, @NotNull String key) {
|
||||
return this.languageManager.getValue(key, getLocale(sender));
|
||||
}
|
||||
|
||||
public @Nullable String getLocalizedMessage(@NotNull CommandSender sender, @NotNull String key, String... replacements) {
|
||||
return this.languageManager.getValue(key, getLocale(sender), replacements);
|
||||
}
|
||||
|
||||
private @Nullable String getLocale(@NotNull CommandSender sender) {
|
||||
if (sender instanceof Player) {
|
||||
return ((Player) sender).getLocale();
|
||||
} else {
|
||||
return this.getConfig().getString("settings.locale", "en_us");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean notifyAnyChest() {
|
||||
return this.getConfig().getBoolean("notify.any-chest", true);
|
||||
|
@ -368,6 +367,8 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
|
||||
this.accessor = new InternalAccessor(this);
|
||||
|
||||
this.languageManager = new LanguageManager(this, "en_us");
|
||||
|
||||
// Version check
|
||||
if (this.accessor.isSupported()) {
|
||||
// Update existing configuration. May require internal access.
|
||||
|
@ -376,35 +377,39 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
// Register listeners
|
||||
pm.registerEvents(new PlayerListener(this), this);
|
||||
pm.registerEvents(new PluginListener(this), this);
|
||||
pm.registerEvents(new InventoryClickListener(), this);
|
||||
pm.registerEvents(new InventoryCloseListener(this), this);
|
||||
// Bukkit will handle missing events for us, attempt to register InventoryDragEvent without a version check
|
||||
pm.registerEvents(new InventoryDragListener(), this);
|
||||
pm.registerEvents(new InventoryListener(this), this);
|
||||
|
||||
// Register commands to their executors
|
||||
OpenInvPluginCommand openInv = new OpenInvPluginCommand(this);
|
||||
this.getCommand("openinv").setExecutor(openInv);
|
||||
this.getCommand("openender").setExecutor(openInv);
|
||||
SearchInvPluginCommand searchInv = new SearchInvPluginCommand(this);
|
||||
this.getCommand("searchinv").setExecutor(searchInv);
|
||||
this.getCommand("searchender").setExecutor(searchInv);
|
||||
this.getCommand("searchenchant").setExecutor(new SearchEnchantPluginCommand(this));
|
||||
this.getCommand("silentchest").setExecutor(new SilentChestPluginCommand(this));
|
||||
this.getCommand("anychest").setExecutor(new AnyChestPluginCommand(this));
|
||||
this.setCommandExecutor(new OpenInvCommand(this), "openinv", "openender");
|
||||
this.setCommandExecutor(new SearchContainerCommand(this), "searchcontainer");
|
||||
this.setCommandExecutor(new SearchInvCommand(this), "searchinv", "searchender");
|
||||
this.setCommandExecutor(new SearchEnchantCommand(this), "searchenchant");
|
||||
this.setCommandExecutor(new ContainerSettingCommand(this), "silentcontainer", "anycontainer");
|
||||
|
||||
} else {
|
||||
this.getLogger().info("Your version of CraftBukkit (" + this.accessor.getVersion() + ") is not supported.");
|
||||
this.getLogger().info("If this version is a recent release, check for an update.");
|
||||
this.getLogger().info("If this is an older version, ensure that you've downloaded the legacy support version.");
|
||||
this.sendVersionError(this.getLogger()::warning);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sendVersionError(Consumer<String> messageMethod) {
|
||||
messageMethod.accept("Your server version (" + this.accessor.getVersion() + ") is not supported.");
|
||||
messageMethod.accept("Please obtain an appropriate version here: " + accessor.getReleasesLink());
|
||||
}
|
||||
|
||||
private void setCommandExecutor(CommandExecutor executor, String... commands) {
|
||||
for (String commandName : commands) {
|
||||
PluginCommand command = this.getCommand(commandName);
|
||||
if (command != null) {
|
||||
command.setExecutor(executor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!this.accessor.isSupported()) {
|
||||
sender.sendMessage("Your version of CraftBukkit (" + this.accessor.getVersion() + ") is not supported.");
|
||||
sender.sendMessage("If this version is a recent release, check for an update.");
|
||||
sender.sendMessage("If this is an older version, ensure that you've downloaded the legacy support version.");
|
||||
this.sendVersionError(sender::sendMessage);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -467,6 +472,9 @@ public class OpenInv extends JavaPlugin implements IOpenInv {
|
|||
return;
|
||||
}
|
||||
|
||||
// Replace stored player with our own version
|
||||
this.playerCache.put(key, this.accessor.getPlayerDataManager().inject(player));
|
||||
|
||||
if (this.inventories.containsKey(key)) {
|
||||
this.inventories.get(key).setPlayerOffline();
|
||||
}
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.commands;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class AnyChestPluginCommand implements CommandExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public AnyChestPluginCommand(final OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "You can't use this from the console.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (args.length > 0 && args[0].equalsIgnoreCase("check")) {
|
||||
sender.sendMessage("AnyChest is " + (this.plugin.getPlayerAnyChestStatus(player) ? "ON" : "OFF") + ".");
|
||||
return true;
|
||||
}
|
||||
|
||||
this.plugin.setPlayerAnyChestStatus(player, !this.plugin.getPlayerAnyChestStatus(player));
|
||||
sender.sendMessage("AnyChest is now " + (this.plugin.getPlayerAnyChestStatus(player) ? "ON" : "OFF") + ".");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2020 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.commands;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.util.TabCompleter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Predicate;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ContainerSettingCommand implements TabExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public ContainerSettingCommand(final OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
plugin.sendMessage(sender, "messages.error.consoleUnsupported");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
boolean any = command.getName().startsWith("any");
|
||||
Predicate<Player> getSetting = any ? plugin::getPlayerAnyChestStatus : plugin::getPlayerSilentChestStatus;
|
||||
BiConsumer<OfflinePlayer, Boolean> setSetting = any ? plugin::setPlayerAnyChestStatus : plugin::setPlayerSilentChestStatus;
|
||||
|
||||
if (args.length > 0) {
|
||||
args[0] = args[0].toLowerCase();
|
||||
|
||||
if (args[0].equals("on")) {
|
||||
setSetting.accept(player, true);
|
||||
} else if (args[0].equals("off")) {
|
||||
setSetting.accept(player, false);
|
||||
} else if (!args[0].equals("check")) {
|
||||
// Invalid argument, show usage.
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
setSetting.accept(player, !getSetting.test(player));
|
||||
}
|
||||
|
||||
String onOff = plugin.getLocalizedMessage(player, getSetting.test(player) ? "messages.info.on" : "messages.info.off");
|
||||
if (onOff == null) {
|
||||
onOff = String.valueOf(getSetting.test(player));
|
||||
}
|
||||
|
||||
plugin.sendMessage(sender, "messages.info.settingState","%setting%", any ? "AnyContainer" : "SilentContainer", "%state%", onOff);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!command.testPermissionSilent(sender) || args.length != 1) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return TabCompleter.completeString(args[0], new String[] {"check", "on", "off"});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -19,33 +19,36 @@ package com.lishid.openinv.commands;
|
|||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.internal.ISpecialInventory;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import com.lishid.openinv.util.TabCompleter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import org.bukkit.ChatColor;
|
||||
import java.util.List;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenInvPluginCommand implements CommandExecutor {
|
||||
public class OpenInvCommand implements TabExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
private final HashMap<Player, String> openInvHistory = new HashMap<Player, String>();
|
||||
private final HashMap<Player, String> openEnderHistory = new HashMap<Player, String>();
|
||||
private final HashMap<Player, String> openInvHistory = new HashMap<>();
|
||||
private final HashMap<Player, String> openEnderHistory = new HashMap<>();
|
||||
|
||||
public OpenInvPluginCommand(final OpenInv plugin) {
|
||||
public OpenInvCommand(final OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) {
|
||||
public boolean onCommand(@NotNull final CommandSender sender, @NotNull final Command command, @NotNull final String label, @NotNull final String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "You can't use this from the console.");
|
||||
plugin.sendMessage(sender, "messages.error.consoleUnsupported");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length > 0 && args[0].equalsIgnoreCase("?")) {
|
||||
if (args.length > 0 && (args[0].equalsIgnoreCase("help") || args[0].equals("?"))) {
|
||||
this.plugin.showHelp((Player) sender);
|
||||
return true;
|
||||
}
|
||||
|
@ -73,10 +76,10 @@ public class OpenInvPluginCommand implements CommandExecutor {
|
|||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final OfflinePlayer offlinePlayer = OpenInvPluginCommand.this.plugin.matchPlayer(name);
|
||||
final OfflinePlayer offlinePlayer = OpenInvCommand.this.plugin.matchPlayer(name);
|
||||
|
||||
if (offlinePlayer == null || !offlinePlayer.hasPlayedBefore() && !offlinePlayer.isOnline()) {
|
||||
player.sendMessage(ChatColor.RED + "Player not found!");
|
||||
plugin.sendMessage(player, "messages.error.invalidPlayer");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -86,9 +89,9 @@ public class OpenInvPluginCommand implements CommandExecutor {
|
|||
if (!player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
OpenInvPluginCommand.this.openInventory(player, offlinePlayer, openinv);
|
||||
OpenInvCommand.this.openInventory(player, offlinePlayer, openinv);
|
||||
}
|
||||
}.runTask(OpenInvPluginCommand.this.plugin);
|
||||
}.runTask(OpenInvCommand.this.plugin);
|
||||
|
||||
}
|
||||
}.runTaskAsynchronously(this.plugin);
|
||||
|
@ -97,49 +100,58 @@ public class OpenInvPluginCommand implements CommandExecutor {
|
|||
}
|
||||
|
||||
private void openInventory(final Player player, final OfflinePlayer target, boolean openinv) {
|
||||
|
||||
|
||||
Player onlineTarget;
|
||||
boolean online = target.isOnline();
|
||||
|
||||
if (!online) {
|
||||
// Try loading the player's data
|
||||
onlineTarget = this.plugin.loadPlayer(target);
|
||||
|
||||
if (onlineTarget == null) {
|
||||
player.sendMessage(ChatColor.RED + "Player not found!");
|
||||
if (Permissions.OPENOFFLINE.hasPermission(player)) {
|
||||
// Try loading the player's data
|
||||
onlineTarget = this.plugin.loadPlayer(target);
|
||||
} else {
|
||||
plugin.sendMessage(player, "messages.error.permissionPlayerOffline");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
onlineTarget = target.getPlayer();
|
||||
if (Permissions.OPENONLINE.hasPermission(player)) {
|
||||
onlineTarget = target.getPlayer();
|
||||
} else {
|
||||
plugin.sendMessage(player, "messages.error.permissionPlayerOnline");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (onlineTarget == null) {
|
||||
plugin.sendMessage(player, "messages.error.invalidPlayer");
|
||||
return;
|
||||
}
|
||||
|
||||
// Permissions checks
|
||||
if (onlineTarget.equals(player)) {
|
||||
// Inventory: Additional permission required to open own inventory
|
||||
if (openinv && !Permissions.OPENSELF.hasPermission(player)) {
|
||||
player.sendMessage(ChatColor.RED + "You're not allowed to open your own inventory!");
|
||||
plugin.sendMessage(player, "messages.error.permissionOpenSelf");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Enderchest: Additional permission required to open others' ender chests
|
||||
if (!openinv && !Permissions.ENDERCHEST_ALL.hasPermission(player)) {
|
||||
player.sendMessage(ChatColor.RED + "You do not have permission to access other players' ender chests.");
|
||||
plugin.sendMessage(player, "messages.error.permissionEnderAll");
|
||||
return;
|
||||
}
|
||||
|
||||
// Protected check
|
||||
if (!Permissions.OVERRIDE.hasPermission(player)
|
||||
&& Permissions.EXEMPT.hasPermission(onlineTarget)) {
|
||||
player.sendMessage(ChatColor.RED + onlineTarget.getDisplayName() + "'s inventory is protected!");
|
||||
plugin.sendMessage(player, "messages.error.permissionExempt",
|
||||
"%target%", onlineTarget.getDisplayName());
|
||||
return;
|
||||
}
|
||||
|
||||
// Crossworld check
|
||||
if (!Permissions.CROSSWORLD.hasPermission(player)
|
||||
&& !onlineTarget.getWorld().equals(player.getWorld())) {
|
||||
player.sendMessage(
|
||||
ChatColor.RED + onlineTarget.getDisplayName() + " is not in your world!");
|
||||
plugin.sendMessage(player, "messages.error.permissionCrossWorld",
|
||||
"%target%", onlineTarget.getDisplayName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +164,7 @@ public class OpenInvPluginCommand implements CommandExecutor {
|
|||
try {
|
||||
inv = openinv ? this.plugin.getSpecialInventory(onlineTarget, online) : this.plugin.getSpecialEnderChest(onlineTarget, online);
|
||||
} catch (Exception e) {
|
||||
player.sendMessage(ChatColor.RED + "An error occurred creating " + onlineTarget.getDisplayName() + "'s inventory!");
|
||||
plugin.sendMessage(player, "messages.error.commandException");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
@ -161,4 +173,13 @@ public class OpenInvPluginCommand implements CommandExecutor {
|
|||
plugin.openInventory(player, inv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!command.testPermissionSilent(sender) || args.length != 1) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return TabCompleter.completeOnlinePlayer(sender, args[0]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2020 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.commands;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.util.TabCompleter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Command for searching containers in a radius of chunks.
|
||||
*/
|
||||
public class SearchContainerCommand implements TabExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public SearchContainerCommand(OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
plugin.sendMessage(sender, "messages.error.consoleUnsupported");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
// Must supply material
|
||||
return false;
|
||||
}
|
||||
|
||||
Material material = Material.getMaterial(args[0].toUpperCase());
|
||||
|
||||
if (material == null) {
|
||||
plugin.sendMessage(sender, "messages.error.invalidMaterial", "%target%", args[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
int radius = 5;
|
||||
|
||||
if (args.length > 1) {
|
||||
try {
|
||||
radius = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
// Invalid radius supplied
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius > 20)
|
||||
{
|
||||
radius = 20;
|
||||
}
|
||||
|
||||
Player senderPlayer = (Player) sender;
|
||||
World world = senderPlayer.getWorld();
|
||||
Chunk centerChunk = senderPlayer.getLocation().getChunk();
|
||||
StringBuilder locations = new StringBuilder();
|
||||
|
||||
for (int dX = -radius; dX <= radius; ++dX) {
|
||||
for (int dZ = -radius; dZ <= radius; ++dZ) {
|
||||
if (!world.loadChunk(centerChunk.getX() + dX, centerChunk.getZ() + dZ, false)) {
|
||||
continue;
|
||||
}
|
||||
Chunk chunk = world.getChunkAt(centerChunk.getX() + dX, centerChunk.getZ() + dZ);
|
||||
for (BlockState tileEntity : chunk.getTileEntities()) {
|
||||
if (!(tileEntity instanceof InventoryHolder)) {
|
||||
continue;
|
||||
}
|
||||
InventoryHolder holder = (InventoryHolder) tileEntity;
|
||||
if (!holder.getInventory().contains(material)) {
|
||||
continue;
|
||||
}
|
||||
locations.append(holder.getInventory().getType().name().toLowerCase()).append(" (")
|
||||
.append(tileEntity.getX()).append(',').append(tileEntity.getY()).append(',')
|
||||
.append(tileEntity.getZ()).append("), ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Matches found, delete trailing comma and space
|
||||
if (locations.length() > 0) {
|
||||
locations.delete(locations.length() - 2, locations.length());
|
||||
} else {
|
||||
plugin.sendMessage(sender, "messages.info.container.noMatches",
|
||||
"%target%", material.name());
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.sendMessage(sender, "messages.info.container.matches",
|
||||
"%target%", material.name(), "%detail%", locations.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
if (args.length < 1 || args.length > 2 || !command.testPermissionSilent(sender)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String argument = args[args.length - 1];
|
||||
if (args.length == 1) {
|
||||
return TabCompleter.completeEnum(argument, Material.class);
|
||||
} else {
|
||||
return TabCompleter.completeInteger(argument);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -17,15 +17,21 @@
|
|||
package com.lishid.openinv.commands;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.util.TabCompleter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Command adding the ability to search online players' inventories for enchantments of a specific
|
||||
|
@ -33,16 +39,16 @@ import org.bukkit.inventory.meta.ItemMeta;
|
|||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
public class SearchEnchantPluginCommand implements CommandExecutor {
|
||||
public class SearchEnchantCommand implements TabExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public SearchEnchantPluginCommand(OpenInv plugin) {
|
||||
public SearchEnchantCommand(OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (args.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -51,14 +57,28 @@ public class SearchEnchantPluginCommand implements CommandExecutor {
|
|||
int level = 0;
|
||||
|
||||
for (String argument : args) {
|
||||
Enchantment localEnchant = Enchantment.getByName(argument.toUpperCase());
|
||||
if (localEnchant != null) {
|
||||
enchant = localEnchant;
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
level = Integer.parseInt(argument);
|
||||
continue;
|
||||
} catch (NumberFormatException ignored) {}
|
||||
|
||||
argument = argument.toLowerCase();
|
||||
int colon = argument.indexOf(':');
|
||||
NamespacedKey key;
|
||||
try {
|
||||
if (colon > -1 && colon < argument.length() - 1) {
|
||||
key = new NamespacedKey(argument.substring(0, colon), argument.substring(colon + 1));
|
||||
} else {
|
||||
key = NamespacedKey.minecraft(argument);
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Enchantment localEnchant = Enchantment.getByKey(key);
|
||||
if (localEnchant != null) {
|
||||
enchant = localEnchant;
|
||||
}
|
||||
}
|
||||
|
||||
// Arguments not set correctly
|
||||
|
@ -94,17 +114,20 @@ public class SearchEnchantPluginCommand implements CommandExecutor {
|
|||
// Matches found, delete trailing comma and space
|
||||
players.delete(players.length() - 2, players.length());
|
||||
} else {
|
||||
sender.sendMessage("No players found with " + (enchant == null ? "any enchant" : enchant.getName())
|
||||
+ " of level " + level + " or higher.");
|
||||
plugin.sendMessage(sender, "messages.info.player.noMatches",
|
||||
"%target%", (enchant != null ? enchant.getKey().toString() : "") + " >= " + level);
|
||||
return true;
|
||||
}
|
||||
|
||||
sender.sendMessage("Players: " + players.toString());
|
||||
plugin.sendMessage(sender, "messages.info.player.matches",
|
||||
"%target%", (enchant != null ? enchant.getKey().toString() : "") + " >= " + level,
|
||||
"%detail%", players.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean containsEnchantment(Inventory inventory, Enchantment enchant, int minLevel) {
|
||||
private boolean containsEnchantment(Inventory inventory, @Nullable Enchantment enchant, int minLevel) {
|
||||
for (ItemStack item : inventory.getContents()) {
|
||||
//noinspection ConstantConditions // Spigot improperly annotated, should be ItemStack @NotNull []
|
||||
if (item == null || item.getType() == Material.AIR) {
|
||||
continue;
|
||||
}
|
||||
|
@ -117,7 +140,7 @@ public class SearchEnchantPluginCommand implements CommandExecutor {
|
|||
continue;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (!meta.hasEnchants()) {
|
||||
if (meta == null || !meta.hasEnchants()) {
|
||||
continue;
|
||||
}
|
||||
for (int enchLevel : meta.getEnchants().values()) {
|
||||
|
@ -130,4 +153,17 @@ public class SearchEnchantPluginCommand implements CommandExecutor {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!command.testPermissionSilent(sender) || args.length < 1 || args.length > 2) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
return TabCompleter.completeObject(args[0], enchantment -> enchantment.getKey().toString(), Enchantment.values());
|
||||
} else {
|
||||
return TabCompleter.completeInteger(args[1]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -17,50 +17,54 @@
|
|||
package com.lishid.openinv.commands;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import org.bukkit.ChatColor;
|
||||
import com.lishid.openinv.util.TabCompleter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SearchInvPluginCommand implements CommandExecutor {
|
||||
public class SearchInvCommand implements TabExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public SearchInvPluginCommand(OpenInv plugin) {
|
||||
public SearchInvCommand(OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
|
||||
Material material = null;
|
||||
int count = 1;
|
||||
|
||||
if (args.length >= 1) {
|
||||
String[] gData = args[0].split(":");
|
||||
material = Material.matchMaterial(gData[0]);
|
||||
material = Material.getMaterial(args[0].toUpperCase());
|
||||
}
|
||||
|
||||
if (material == null) {
|
||||
plugin.sendMessage(sender, "messages.error.invalidMaterial", "%target%", args.length > 0 ? args[0] : "null");
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 1;
|
||||
|
||||
if (args.length >= 2) {
|
||||
try {
|
||||
count = Integer.parseInt(args[1]);
|
||||
} catch (NumberFormatException ex) {
|
||||
sender.sendMessage(ChatColor.RED + "'" + args[1] + "' is not a number!");
|
||||
plugin.sendMessage(sender, "messages.error.invalidNumber", "%target%", args[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (material == null) {
|
||||
sender.sendMessage(ChatColor.RED + "Unknown item");
|
||||
return false;
|
||||
}
|
||||
|
||||
StringBuilder players = new StringBuilder();
|
||||
boolean searchInv = command.getName().equals("searchinv");
|
||||
for (Player player : plugin.getServer().getOnlinePlayers()) {
|
||||
Inventory inventory = command.getName().equals("searchinv") ? player.getInventory() : player.getEnderChest();
|
||||
Inventory inventory = searchInv ? player.getInventory() : player.getEnderChest();
|
||||
if (inventory.contains(material, count)) {
|
||||
players.append(player.getName()).append(", ");
|
||||
}
|
||||
|
@ -70,11 +74,28 @@ public class SearchInvPluginCommand implements CommandExecutor {
|
|||
if (players.length() > 0) {
|
||||
players.delete(players.length() - 2, players.length());
|
||||
} else {
|
||||
sender.sendMessage("No players found with " + material.toString());
|
||||
plugin.sendMessage(sender, "messages.info.player.noMatches",
|
||||
"%target%", material.name());
|
||||
return true;
|
||||
}
|
||||
|
||||
sender.sendMessage("Players with the item " + material.toString() + ": " + players.toString());
|
||||
plugin.sendMessage(sender, "messages.info.player.matches",
|
||||
"%target%", material.name(), "%detail%", players.toString());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (args.length < 1 || args.length > 2 || !command.testPermissionSilent(sender)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String argument = args[args.length - 1];
|
||||
if (args.length == 1) {
|
||||
return TabCompleter.completeEnum(argument, Material.class);
|
||||
} else {
|
||||
return TabCompleter.completeInteger(argument);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.commands;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class SilentChestPluginCommand implements CommandExecutor {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public SilentChestPluginCommand(OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(ChatColor.RED + "You can't use this from the console.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
|
||||
if (args.length > 0 && args[0].equalsIgnoreCase("check")) {
|
||||
sender.sendMessage("SilentChest is " + (plugin.getPlayerAnyChestStatus(player) ? "ON" : "OFF") + ".");
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.setPlayerSilentChestStatus(player, !plugin.getPlayerSilentChestStatus(player));
|
||||
sender.sendMessage("SilentChest is now " + (plugin.getPlayerSilentChestStatus(player) ? "ON" : "OFF") + ".");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -34,6 +34,13 @@ public interface IPlayerDataManager {
|
|||
*/
|
||||
@Nullable Player loadPlayer(@NotNull 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);
|
||||
|
||||
/**
|
||||
* Opens an ISpecialInventory for a Player.
|
||||
*
|
||||
|
@ -42,6 +49,18 @@ public interface IPlayerDataManager {
|
|||
*`
|
||||
* @return the InventoryView opened
|
||||
*/
|
||||
InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory);
|
||||
@Nullable InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory);
|
||||
|
||||
/**
|
||||
* Convert a raw slot number into a player inventory slot number.
|
||||
*
|
||||
* <p>Note that this method is specifically for converting an ISpecialPlayerInventory slot number into a regular
|
||||
* player inventory slot number.
|
||||
*
|
||||
* @param view the open inventory view
|
||||
* @param rawSlot the raw slot in the view
|
||||
* @return the converted slot number
|
||||
*/
|
||||
int convertToPlayerSlot(InventoryView view, int rawSlot);
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.lishid.openinv.internal;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class OpenInventoryView extends InventoryView {
|
||||
|
||||
private final Player player;
|
||||
private final ISpecialInventory inventory;
|
||||
private final String titleKey;
|
||||
private final String titleDefaultSuffix;
|
||||
private String title;
|
||||
|
||||
public OpenInventoryView(Player player, ISpecialInventory inventory, String titleKey, String titleDefaultSuffix) {
|
||||
this.player = player;
|
||||
this.inventory = inventory;
|
||||
this.titleKey = titleKey;
|
||||
this.titleDefaultSuffix = titleDefaultSuffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getTopInventory() {
|
||||
return inventory.getBukkitInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Inventory getBottomInventory() {
|
||||
return getPlayer().getInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HumanEntity getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull InventoryType getType() {
|
||||
return inventory.getBukkitInventory().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTitle() {
|
||||
if (title == null) {
|
||||
HumanEntity owner = getPlayer();
|
||||
|
||||
String localTitle = OpenInv.getPlugin(OpenInv.class)
|
||||
.getLocalizedMessage(
|
||||
owner,
|
||||
titleKey,
|
||||
"%player%",
|
||||
owner.getName());
|
||||
if (localTitle != null) {
|
||||
title = localTitle;
|
||||
} else {
|
||||
title = owner.getName() + titleDefaultSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.listeners;
|
||||
|
||||
import com.lishid.openinv.util.InventoryAccess;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
public class InventoryClickListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
HumanEntity entity = event.getWhoClicked();
|
||||
Inventory inventory = event.getInventory();
|
||||
if (InventoryAccess.isPlayerInventory(inventory) && !Permissions.EDITINV.hasPermission(entity)
|
||||
|| InventoryAccess.isEnderChest(inventory) && !Permissions.EDITENDER.hasPermission(entity)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 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.listeners;
|
||||
|
||||
import com.lishid.openinv.IOpenInv;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
|
||||
public class InventoryCloseListener implements Listener {
|
||||
|
||||
private final IOpenInv plugin;
|
||||
|
||||
public InventoryCloseListener(final IOpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(final InventoryCloseEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) event.getPlayer();
|
||||
|
||||
if (this.plugin.getPlayerSilentChestStatus(player)) {
|
||||
this.plugin.getAnySilentContainer().deactivateContainer(player);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2019 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.listeners;
|
||||
|
||||
import com.lishid.openinv.util.InventoryAccess;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
|
||||
/**
|
||||
* Listener for InventoryDragEvents to prevent unpermitted modification of special inventories.
|
||||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
public class InventoryDragListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||
public void onInventoryDrag(InventoryDragEvent event) {
|
||||
HumanEntity entity = event.getWhoClicked();
|
||||
Inventory inventory = event.getInventory();
|
||||
if (InventoryAccess.isPlayerInventory(inventory) && !Permissions.EDITINV.hasPermission(entity)
|
||||
|| InventoryAccess.isEnderChest(inventory) && !Permissions.EDITENDER.hasPermission(entity)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2020 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.listeners;
|
||||
|
||||
import com.lishid.openinv.OpenInv;
|
||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
|
||||
import com.lishid.openinv.util.InventoryAccess;
|
||||
import com.lishid.openinv.util.Permissions;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryDragEvent;
|
||||
import org.bukkit.event.inventory.InventoryInteractEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Listener for inventory-related events to prevent modification of inventories where not allowed.
|
||||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
public class InventoryListener implements Listener {
|
||||
|
||||
private final OpenInv plugin;
|
||||
|
||||
public InventoryListener(final OpenInv plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClose(@NotNull final InventoryCloseEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) event.getPlayer();
|
||||
|
||||
if (this.plugin.getPlayerSilentChestStatus(player)) {
|
||||
this.plugin.getAnySilentContainer().deactivateContainer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onInventoryClick(@NotNull final InventoryClickEvent event) {
|
||||
if (handleInventoryInteract(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Safe cast - has to be a player to be the holder of a special player inventory.
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
|
||||
if (event.getAction() != InventoryAction.MOVE_TO_OTHER_INVENTORY) {
|
||||
// All own-inventory interactions require updates to display properly.
|
||||
// Update in same tick after event completion.
|
||||
this.plugin.getServer().getScheduler().runTask(this.plugin, player::updateInventory);
|
||||
return;
|
||||
}
|
||||
|
||||
// Extra handling for MOVE_TO_OTHER_INVENTORY - apparently Mojang no longer removes the item from the target
|
||||
// inventory prior to adding it to existing stacks.
|
||||
ItemStack currentItem = event.getCurrentItem();
|
||||
if (currentItem == null) {
|
||||
// Other plugin doing some sort of handling (would be NOTHING for null item otherwise), ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack clone = currentItem.clone();
|
||||
event.setCurrentItem(null);
|
||||
|
||||
// Complete add action in same tick after event completion.
|
||||
this.plugin.getServer().getScheduler().runTask(this.plugin, () -> {
|
||||
player.getInventory().addItem(clone);
|
||||
player.updateInventory();
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onInventoryDrag(@NotNull final InventoryDragEvent event) {
|
||||
if (handleInventoryInteract(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryView view = event.getView();
|
||||
int topSize = view.getTopInventory().getSize();
|
||||
|
||||
// Get bottom inventory active slots as player inventory slots.
|
||||
Set<Integer> slots = event.getRawSlots().stream()
|
||||
.filter(slot -> slot >= topSize)
|
||||
.map(slot -> plugin.convertToPlayerSlot(view, slot)).collect(Collectors.toSet());
|
||||
|
||||
int overlapLosses = 0;
|
||||
|
||||
// Count overlapping slots.
|
||||
for (Map.Entry<Integer, ItemStack> newItem : event.getNewItems().entrySet()) {
|
||||
int rawSlot = newItem.getKey();
|
||||
|
||||
// Skip bottom inventory slots.
|
||||
if (rawSlot >= topSize) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int convertedSlot = plugin.convertToPlayerSlot(view, rawSlot);
|
||||
|
||||
if (slots.contains(convertedSlot)) {
|
||||
overlapLosses += getCountDiff(view.getItem(rawSlot), newItem.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Allow no overlap to proceed as usual.
|
||||
if (overlapLosses < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack cursor = event.getCursor();
|
||||
if (cursor != null) {
|
||||
cursor.setAmount(cursor.getAmount() + overlapLosses);
|
||||
} else {
|
||||
cursor = event.getOldCursor().clone();
|
||||
cursor.setAmount(overlapLosses);
|
||||
}
|
||||
|
||||
event.setCursor(cursor);
|
||||
}
|
||||
|
||||
private int getCountDiff(@Nullable ItemStack original, @NotNull ItemStack result) {
|
||||
if (original == null || original.getType() != result.getType()) {
|
||||
return result.getAmount();
|
||||
}
|
||||
|
||||
return result.getAmount() - original.getAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle common InventoryInteractEvent functions.
|
||||
*
|
||||
* @param event the InventoryInteractEvent
|
||||
* @return true unless the top inventory is the holder's own inventory
|
||||
*/
|
||||
private boolean handleInventoryInteract(@NotNull final InventoryInteractEvent event) {
|
||||
HumanEntity entity = event.getWhoClicked();
|
||||
|
||||
// Un-cancel spectator interactions.
|
||||
if (Permissions.SPECTATE.hasPermission(entity) && entity.getGameMode() == GameMode.SPECTATOR) {
|
||||
event.setCancelled(false);
|
||||
}
|
||||
|
||||
if (event.isCancelled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory inventory = event.getView().getTopInventory();
|
||||
|
||||
// Is the inventory a special ender chest?
|
||||
if (InventoryAccess.isEnderChest(inventory)) {
|
||||
// Disallow ender chest interaction for users without edit permission.
|
||||
if (!Permissions.EDITENDER.hasPermission(entity)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ISpecialPlayerInventory playerInventory = InventoryAccess.getPlayerInventory(inventory);
|
||||
|
||||
// Ignore inventories other than special player inventories.
|
||||
if (playerInventory == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Disallow player inventory interaction for users without edit permission.
|
||||
if (!Permissions.EDITINV.hasPermission(entity)) {
|
||||
event.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only specially handle actions in the player's own inventory.
|
||||
return !event.getWhoClicked().equals(event.getView().getTopInventory().getHolder());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -37,7 +37,7 @@ public class PlayerListener implements Listener {
|
|||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||
plugin.setPlayerOnline(event.getPlayer());
|
||||
}
|
||||
|
@ -54,8 +54,14 @@ public class PlayerListener implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
|
||||
// Do not cancel 3rd party plugins' custom events
|
||||
if (!PlayerInteractEvent.class.equals(event.getClass())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK || event.getPlayer().isSneaking()
|
||||
|| event.useInteractedBlock() == Result.DENY
|
||||
|| event.useInteractedBlock() == Result.DENY || event.getClickedBlock() == null
|
||||
|| !plugin.getAnySilentContainer().isAnySilentContainer(event.getClickedBlock())) {
|
||||
return;
|
||||
}
|
||||
|
@ -71,13 +77,15 @@ public class PlayerListener implements Listener {
|
|||
boolean silent = Permissions.SILENT.hasPermission(player) && plugin.getPlayerSilentChestStatus(player);
|
||||
|
||||
// If anycontainer or silentcontainer is active
|
||||
if ((any || silent) && plugin.getAnySilentContainer().activateContainer(player, silent, event.getClickedBlock())) {
|
||||
if (silent && plugin.notifySilentChest() && needsAny && plugin.notifyAnyChest()) {
|
||||
player.sendMessage("You are opening a blocked container silently.");
|
||||
} else if (silent && plugin.notifySilentChest()) {
|
||||
player.sendMessage("You are opening a container silently.");
|
||||
} else if (needsAny && plugin.notifyAnyChest()) {
|
||||
player.sendMessage("You are opening a blocked container.");
|
||||
if (any || silent) {
|
||||
if (plugin.getAnySilentContainer().activateContainer(player, silent, event.getClickedBlock())) {
|
||||
if (silent && plugin.notifySilentChest() && needsAny && plugin.notifyAnyChest()) {
|
||||
plugin.sendSystemMessage(player, "messages.info.containerBlockedSilent");
|
||||
} else if (needsAny && plugin.notifyAnyChest()) {
|
||||
plugin.sendSystemMessage(player, "messages.info.containerBlocked");
|
||||
} else if (silent && plugin.notifySilentChest()) {
|
||||
plugin.sendSystemMessage(player, "messages.info.containerSilent");
|
||||
}
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -19,11 +19,13 @@ package com.lishid.openinv.util;
|
|||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.TreeMultimap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A minimal thread-safe time-based cache implementation backed by a HashMap and TreeMultimap.
|
||||
|
@ -35,30 +37,20 @@ public class Cache<K, V> {
|
|||
private final Map<K, V> internal;
|
||||
private final Multimap<Long, K> expiry;
|
||||
private final long retention;
|
||||
private final Function<V> inUseCheck, postRemoval;
|
||||
private final Predicate<V> inUseCheck;
|
||||
private final Consumer<V> postRemoval;
|
||||
|
||||
/**
|
||||
* Constructs a Cache with the specified retention duration, in use function, and post-removal function.
|
||||
*
|
||||
* @param retention duration after which keys are automatically invalidated if not in use
|
||||
* @param inUseCheck Function used to check if a key is considered in use
|
||||
* @param postRemoval Function used to perform any operations required when a key is invalidated
|
||||
* @param inUseCheck Predicate used to check if a key is considered in use
|
||||
* @param postRemoval Consumer used to perform any operations required when a key is invalidated
|
||||
*/
|
||||
public Cache(final long retention, final Function<V> inUseCheck, final Function<V> postRemoval) {
|
||||
this.internal = new HashMap<K, V>();
|
||||
public Cache(final long retention, final Predicate<V> inUseCheck, final Consumer<V> postRemoval) {
|
||||
this.internal = new HashMap<>();
|
||||
|
||||
this.expiry = TreeMultimap.create(new Comparator<Long>() {
|
||||
@Override
|
||||
public int compare(final Long long1, final Long long2) {
|
||||
return long1.compareTo(long2);
|
||||
}
|
||||
},
|
||||
new Comparator<K>() {
|
||||
@Override
|
||||
public int compare(final K k1, final K k2) {
|
||||
return k1 == k2 || k1 != null && k1.equals(k2) ? 0 : 1;
|
||||
}
|
||||
});
|
||||
this.expiry = TreeMultimap.create(Long::compareTo, (k1, k2) -> Objects.equals(k1, k2) ? 0 : 1);
|
||||
|
||||
this.retention = retention;
|
||||
this.inUseCheck = inUseCheck;
|
||||
|
@ -146,7 +138,7 @@ public class Cache<K, V> {
|
|||
public void invalidateAll() {
|
||||
synchronized (this.internal) {
|
||||
for (V value : this.internal.values()) {
|
||||
this.postRemoval.run(value);
|
||||
this.postRemoval.accept(value);
|
||||
}
|
||||
this.expiry.clear();
|
||||
this.internal.clear();
|
||||
|
@ -160,7 +152,7 @@ public class Cache<K, V> {
|
|||
private void lazyCheck() {
|
||||
long now = System.currentTimeMillis();
|
||||
synchronized (this.internal) {
|
||||
List<K> inUse = new ArrayList<K>();
|
||||
List<K> inUse = new ArrayList<>();
|
||||
for (Iterator<Map.Entry<Long, K>> iterator = this.expiry.entries().iterator(); iterator
|
||||
.hasNext();) {
|
||||
Map.Entry<Long, K> entry = iterator.next();
|
||||
|
@ -171,7 +163,7 @@ public class Cache<K, V> {
|
|||
|
||||
iterator.remove();
|
||||
|
||||
if (this.inUseCheck.run(this.internal.get(entry.getValue()))) {
|
||||
if (this.inUseCheck.test(this.internal.get(entry.getValue()))) {
|
||||
inUse.add(entry.getValue());
|
||||
continue;
|
||||
}
|
||||
|
@ -182,7 +174,7 @@ public class Cache<K, V> {
|
|||
continue;
|
||||
}
|
||||
|
||||
this.postRemoval.run(value);
|
||||
this.postRemoval.accept(value);
|
||||
}
|
||||
|
||||
long nextExpiry = now + this.retention;
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -24,7 +24,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public class ConfigUpdater {
|
||||
|
||||
|
@ -36,7 +35,8 @@ public class ConfigUpdater {
|
|||
|
||||
public void checkForUpdates() {
|
||||
final int version = plugin.getConfig().getInt("config-version", 1);
|
||||
if (version >= plugin.getConfig().getDefaults().getInt("config-version")) {
|
||||
ConfigurationSection defaults = plugin.getConfig().getDefaults();
|
||||
if (defaults == null || version >= defaults.getInt("config-version")) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,73 +50,72 @@ public class ConfigUpdater {
|
|||
plugin.getLogger().warning("Could not back up config.yml before updating!");
|
||||
}
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (version < 2) {
|
||||
updateConfig1To2();
|
||||
}
|
||||
if (version < 3) {
|
||||
updateConfig2To3();
|
||||
}
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.saveConfig();
|
||||
plugin.getLogger().info("Configuration update complete!");
|
||||
}
|
||||
}.runTaskLater(plugin, 1L); // Run on 1 tick delay; on older versions Bukkit's scheduler is not guaranteed FIFO
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
if (version < 2) {
|
||||
updateConfig1To2();
|
||||
}
|
||||
}.runTaskAsynchronously(plugin);
|
||||
if (version < 3) {
|
||||
updateConfig2To3();
|
||||
}
|
||||
if (version < 4) {
|
||||
updateConfig3To4();
|
||||
}
|
||||
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
plugin.saveConfig();
|
||||
plugin.getLogger().info("Configuration update complete!");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConfig3To4() {
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
plugin.getConfig().set("notify", null);
|
||||
plugin.getConfig().set("settings.locale", "en_US");
|
||||
plugin.getConfig().set("config-version", 4);
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConfig2To3() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plugin.getConfig().set("config-version", 3);
|
||||
plugin.getConfig().set("items.open-inv", null);
|
||||
plugin.getConfig().set("ItemOpenInv", null);
|
||||
plugin.getConfig().set("toggles.items.open-inv", null);
|
||||
plugin.getConfig().set("settings.disable-saving",
|
||||
plugin.getConfig().getBoolean("DisableSaving", false));
|
||||
plugin.getConfig().set("DisableSaving", null);
|
||||
}
|
||||
}.runTask(plugin);
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
plugin.getConfig().set("config-version", 3);
|
||||
plugin.getConfig().set("items.open-inv", null);
|
||||
plugin.getConfig().set("ItemOpenInv", null);
|
||||
plugin.getConfig().set("toggles.items.open-inv", null);
|
||||
plugin.getConfig().set("settings.disable-saving",
|
||||
plugin.getConfig().getBoolean("DisableSaving", false));
|
||||
plugin.getConfig().set("DisableSaving", null);
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConfig1To2() {
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Get the old config settings
|
||||
boolean notifySilentChest = plugin.getConfig().getBoolean("NotifySilentChest", true);
|
||||
boolean notifyAnyChest = plugin.getConfig().getBoolean("NotifyAnyChest", true);
|
||||
plugin.getConfig().set("ItemOpenInvItemID", null);
|
||||
plugin.getConfig().set("NotifySilentChest", null);
|
||||
plugin.getConfig().set("NotifyAnyChest", null);
|
||||
plugin.getConfig().set("config-version", 2);
|
||||
plugin.getConfig().set("notify.any-chest", notifyAnyChest);
|
||||
plugin.getConfig().set("notify.silent-chest", notifySilentChest);
|
||||
}
|
||||
}.runTask(plugin);
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
// Get the old config settings
|
||||
boolean notifySilentChest = plugin.getConfig().getBoolean("NotifySilentChest", true);
|
||||
boolean notifyAnyChest = plugin.getConfig().getBoolean("NotifyAnyChest", true);
|
||||
plugin.getConfig().set("ItemOpenInvItemID", null);
|
||||
plugin.getConfig().set("NotifySilentChest", null);
|
||||
plugin.getConfig().set("NotifyAnyChest", null);
|
||||
plugin.getConfig().set("config-version", 2);
|
||||
plugin.getConfig().set("notify.any-chest", notifyAnyChest);
|
||||
plugin.getConfig().set("notify.silent-chest", notifySilentChest);
|
||||
});
|
||||
|
||||
updateToggles("AnyChest", "toggles.any-chest");
|
||||
updateToggles("SilentChest", "toggles.silent-chest");
|
||||
}
|
||||
|
||||
private void updateToggles(final String sectionName, final String newSectionName) {
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection(sectionName);
|
||||
// Ensure section exists
|
||||
if (!plugin.getConfig().isConfigurationSection(sectionName)) {
|
||||
if (section == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection(sectionName);
|
||||
Set<String> keys = section.getKeys(false);
|
||||
|
||||
// Ensure section has content
|
||||
if (keys == null || keys.isEmpty()) {
|
||||
if (keys.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,25 +128,20 @@ public class ConfigUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Wipe old ConfigurationSection
|
||||
plugin.getConfig().set(sectionName, null);
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
// Wipe old ConfigurationSection
|
||||
plugin.getConfig().set(sectionName, null);
|
||||
|
||||
// Prepare new ConfigurationSection
|
||||
ConfigurationSection newSection;
|
||||
if (plugin.getConfig().isConfigurationSection(newSectionName)) {
|
||||
newSection = plugin.getConfig().getConfigurationSection(newSectionName);
|
||||
} else {
|
||||
newSection = plugin.getConfig().createSection(newSectionName);
|
||||
}
|
||||
// Set new values
|
||||
for (Map.Entry<String, Boolean> entry : toggles.entrySet()) {
|
||||
newSection.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
// Prepare new ConfigurationSection
|
||||
ConfigurationSection newSection = plugin.getConfig().getConfigurationSection(newSectionName);
|
||||
if (newSection == null) {
|
||||
newSection = plugin.getConfig().createSection(newSectionName);
|
||||
}
|
||||
}.runTask(plugin);
|
||||
// Set new values
|
||||
for (Map.Entry<String, Boolean> entry : toggles.entrySet()) {
|
||||
newSection.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -40,15 +40,54 @@ public class InternalAccessor {
|
|||
this.version = packageName.substring(packageName.lastIndexOf('.') + 1);
|
||||
|
||||
try {
|
||||
// TODO: implement support for CraftMagicNumbers#getMappingsVersion
|
||||
Class.forName("com.lishid.openinv.internal." + this.version + ".SpecialPlayerInventory");
|
||||
Class.forName("com.lishid.openinv.internal." + this.version + ".SpecialEnderChest");
|
||||
this.playerDataManager = this.createObject(IPlayerDataManager.class, "PlayerDataManager");
|
||||
this.anySilentContainer = this.createObject(IAnySilentContainer.class, "AnySilentContainer");
|
||||
this.supported = InventoryAccess.isUseable();
|
||||
this.supported = InventoryAccess.isUsable();
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
public String getReleasesLink() {
|
||||
switch (version) {
|
||||
case "1_4_5":
|
||||
case "1_4_6":
|
||||
case "v1_4_R1":
|
||||
case "v1_5_R2":
|
||||
case "v1_5_R3":
|
||||
case "v1_6_R1":
|
||||
case "v1_6_R2":
|
||||
case "v1_6_R3":
|
||||
case "v1_7_R1":
|
||||
case "v1_7_R2":
|
||||
case "v1_7_R3":
|
||||
case "v1_7_R4":
|
||||
case "v1_8_R1":
|
||||
case "v1_8_R2":
|
||||
case "v1_9_R1":
|
||||
case "v1_9_R2":
|
||||
case "v1_10_R1":
|
||||
case "v1_11_R1":
|
||||
case "v1_12_R1":
|
||||
return "https://github.com/lishid/OpenInv/releases/tag/4.0.0 (OpenInv-legacy)";
|
||||
case "v1_13_R1":
|
||||
return "https://github.com/lishid/OpenInv/releases/tag/4.0.0";
|
||||
case "v1_13_R2":
|
||||
return "https://github.com/lishid/OpenInv/releases/tag/4.0.7";
|
||||
case "v1_14_R1":
|
||||
return "https://github.com/lishid/OpenInv/releases/tag/4.1.1";
|
||||
case "v1_16_R1":
|
||||
return "https://github.com/lishid/OpenInv/releases/tag/4.1.4";
|
||||
case "v1_8_R3":
|
||||
case "v1_15_R1":
|
||||
case "v1_16_R2":
|
||||
return "https://github.com/lishid/OpenInv/releases/tag/4.1.5";
|
||||
case "v1_16_R3":
|
||||
default:
|
||||
return "https://github.com/lishid/OpenInv/releases";
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T createObject(final Class<? extends T> assignableClass, final String className,
|
||||
final Object... params) throws ClassCastException, ClassNotFoundException,
|
||||
InstantiationException, IllegalAccessException, IllegalArgumentException,
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2020 Jikoo. 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 com.lishid.openinv.OpenInv;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A simple language manager supporting both custom and bundled languages.
|
||||
*
|
||||
* @author Jikoo
|
||||
*/
|
||||
public class LanguageManager {
|
||||
|
||||
private final OpenInv plugin;
|
||||
private final String defaultLocale;
|
||||
private final Map<String, YamlConfiguration> locales;
|
||||
|
||||
public LanguageManager(@NotNull OpenInv plugin, @NotNull String defaultLocale) {
|
||||
this.plugin = plugin;
|
||||
this.defaultLocale = defaultLocale;
|
||||
this.locales = new HashMap<>();
|
||||
getOrLoadLocale(defaultLocale);
|
||||
}
|
||||
|
||||
private YamlConfiguration getOrLoadLocale(@NotNull String locale) {
|
||||
YamlConfiguration loaded = locales.get(locale);
|
||||
if (loaded != null) {
|
||||
return loaded;
|
||||
}
|
||||
|
||||
InputStream resourceStream = plugin.getResource(locale + ".yml");
|
||||
YamlConfiguration localeConfigDefaults;
|
||||
if (resourceStream == null) {
|
||||
localeConfigDefaults = new YamlConfiguration();
|
||||
} else {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceStream))) {
|
||||
localeConfigDefaults = YamlConfiguration.loadConfiguration(reader);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Unable to load resource " + locale + ".yml", e);
|
||||
localeConfigDefaults = new YamlConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(plugin.getDataFolder(), locale + ".yml");
|
||||
YamlConfiguration localeConfig;
|
||||
|
||||
if (!file.exists()) {
|
||||
localeConfig = localeConfigDefaults;
|
||||
try {
|
||||
localeConfigDefaults.save(file);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Unable to save resource " + locale + ".yml", e);
|
||||
}
|
||||
} else {
|
||||
localeConfig = YamlConfiguration.loadConfiguration(file);
|
||||
|
||||
// Add new language keys
|
||||
List<String> newKeys = new ArrayList<>();
|
||||
for (String key : localeConfigDefaults.getKeys(true)) {
|
||||
if (localeConfigDefaults.isConfigurationSection(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (localeConfig.isSet(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
localeConfig.set(key, localeConfigDefaults.get(key));
|
||||
newKeys.add(key);
|
||||
}
|
||||
|
||||
if (!newKeys.isEmpty()) {
|
||||
plugin.getLogger().info("[LanguageManager] Added new language keys: " + String.join(", ", newKeys));
|
||||
try {
|
||||
localeConfig.save(file);
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Unable to save resource " + locale + ".yml", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!locale.equals(defaultLocale)) {
|
||||
localeConfigDefaults = locales.get(defaultLocale);
|
||||
|
||||
// Check for missing keys
|
||||
List<String> newKeys = new ArrayList<>();
|
||||
for (String key : localeConfigDefaults.getKeys(true)) {
|
||||
if (localeConfigDefaults.isConfigurationSection(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (localeConfig.isSet(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
newKeys.add(key);
|
||||
}
|
||||
|
||||
if (!newKeys.isEmpty()) {
|
||||
plugin.getLogger().info("[LanguageManager] Missing translations from " + locale + ".yml: " + String.join(", ", newKeys));
|
||||
}
|
||||
|
||||
// Fall through to default locale
|
||||
localeConfig.setDefaults(localeConfigDefaults);
|
||||
}
|
||||
|
||||
locales.put(locale, localeConfig);
|
||||
return localeConfig;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getValue(@NotNull String key, @Nullable String locale) {
|
||||
String value = getOrLoadLocale(locale == null ? defaultLocale : locale.toLowerCase()).getString(key);
|
||||
if (value == null || value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
value = ChatColor.translateAlternateColorCodes('&', value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getValue(@NotNull String key, @Nullable String locale, @NotNull String... replacements) {
|
||||
if (replacements.length % 2 != 0) {
|
||||
plugin.getLogger().log(Level.WARNING, "[LanguageManager] Replacement data is uneven", new Exception());
|
||||
}
|
||||
|
||||
String value = getValue(key, locale);
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < replacements.length; i += 2) {
|
||||
value = value.replace(replacements[i], replacements[i + 1]);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
* Copyright (C) 2011-2020 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
|
||||
|
@ -25,26 +25,35 @@ public enum Permissions {
|
|||
EXEMPT("exempt"),
|
||||
CROSSWORLD("crossworld"),
|
||||
SILENT("silent"),
|
||||
SILENT_DEFAULT("silent.default"),
|
||||
SILENT_DEFAULT("silent.default", true),
|
||||
ANYCHEST("anychest"),
|
||||
ANY_DEFAULT("any.default"),
|
||||
ANY_DEFAULT("any.default", true),
|
||||
ENDERCHEST("openender"),
|
||||
ENDERCHEST_ALL("openenderall"),
|
||||
SEARCH("search"),
|
||||
EDITINV("editinv"),
|
||||
EDITENDER("editender"),
|
||||
OPENSELF("openself");
|
||||
OPENSELF("openself"),
|
||||
OPENONLINE("openonline"),
|
||||
OPENOFFLINE("openoffline"),
|
||||
SPECTATE("spectate");
|
||||
|
||||
private final String permission;
|
||||
private final boolean uninheritable;
|
||||
|
||||
Permissions(String permission) {
|
||||
this(permission, false);
|
||||
}
|
||||
|
||||
Permissions(String permission, boolean uninheritable) {
|
||||
this.permission = "OpenInv." + permission;
|
||||
this.uninheritable = uninheritable;
|
||||
}
|
||||
|
||||
public boolean hasPermission(Permissible permissible) {
|
||||
|
||||
boolean hasPermission = permissible.hasPermission(permission);
|
||||
if (hasPermission || permissible.isPermissionSet(permission)) {
|
||||
if (uninheritable || hasPermission || permissible.isPermissionSet(permission)) {
|
||||
return hasPermission;
|
||||
}
|
||||
|
147
plugin/src/main/java/com/lishid/openinv/util/TabCompleter.java
Normal file
147
plugin/src/main/java/com/lishid/openinv/util/TabCompleter.java
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2020 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 java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Function;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Utility class for common tab completions.
|
||||
*/
|
||||
public class TabCompleter {
|
||||
|
||||
/**
|
||||
* Offer tab completions for whole numbers.
|
||||
*
|
||||
* @param argument the argument to complete
|
||||
* @return integer options
|
||||
*/
|
||||
public static List<String> completeInteger(String argument) {
|
||||
// Ensure existing argument is actually a number
|
||||
if (!argument.isEmpty()) {
|
||||
try {
|
||||
Integer.parseInt(argument);
|
||||
} catch (NumberFormatException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
List<String> completions = new ArrayList<>(10);
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
completions.add(argument + i);
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer tab completions for a given Enum.
|
||||
*
|
||||
* @param argument the argument to complete
|
||||
* @param enumClazz the Enum to complete for
|
||||
* @return the matching Enum values
|
||||
*/
|
||||
public static List<String> completeEnum(String argument, Class<? extends Enum<?>> enumClazz) {
|
||||
argument = argument.toLowerCase(Locale.ENGLISH);
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
for (Enum<?> enumConstant : enumClazz.getEnumConstants()) {
|
||||
String name = enumConstant.name().toLowerCase();
|
||||
if (name.startsWith(argument)) {
|
||||
completions.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer tab completions for a given array of Strings.
|
||||
*
|
||||
* @param argument the argument to complete
|
||||
* @param options the Strings which may be completed
|
||||
* @return the matching Strings
|
||||
*/
|
||||
public static List<String> completeString(String argument, String[] options) {
|
||||
argument = argument.toLowerCase(Locale.ENGLISH);
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
for (String option : options) {
|
||||
if (option.startsWith(argument)) {
|
||||
completions.add(option);
|
||||
}
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer tab completions for visible online Players' names.
|
||||
*
|
||||
* @param sender the command's sender
|
||||
* @param argument the argument to complete
|
||||
* @return the matching Players' names
|
||||
*/
|
||||
public static List<String> completeOnlinePlayer(CommandSender sender, String argument) {
|
||||
List<String> completions = new ArrayList<>();
|
||||
Player senderPlayer = sender instanceof Player ? (Player) sender : null;
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (senderPlayer != null && !senderPlayer.canSee(player)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (StringUtil.startsWithIgnoreCase(player.getName(), argument)) {
|
||||
completions.add(player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offer tab completions for a given array of Objects.
|
||||
*
|
||||
* @param argument the argument to complete
|
||||
* @param converter the Function for converting the Object into a comparable String
|
||||
* @param options the Objects which may be completed
|
||||
* @return the matching Strings
|
||||
*/
|
||||
public static <T> List<String> completeObject(String argument, Function<T, String> converter, T[] options) {
|
||||
argument = argument.toLowerCase(Locale.ENGLISH);
|
||||
List<String> completions = new ArrayList<>();
|
||||
|
||||
for (T option : options) {
|
||||
String optionString = converter.apply(option).toLowerCase();
|
||||
if (optionString.startsWith(argument)) {
|
||||
completions.add(optionString);
|
||||
}
|
||||
}
|
||||
|
||||
return completions;
|
||||
}
|
||||
|
||||
private TabCompleter() {}
|
||||
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
config-version: 3
|
||||
notify:
|
||||
any-chest: true
|
||||
silent-chest: true
|
||||
config-version: 4
|
||||
settings:
|
||||
disable-saving: false
|
||||
locale: 'en_us'
|
||||
|
|
30
plugin/src/main/resources/de_de.yml
Normal file
30
plugin/src/main/resources/de_de.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
messages:
|
||||
error:
|
||||
consoleUnsupported: 'Du kannst diesen Befehl nicht von der Konsole ausführen.'
|
||||
lootNotGenerated: '&cBeute noch nicht erstellt! Bitte schalte &b/silentcontainer&c aus.'
|
||||
invalidMaterial: '&cUngültiges Material: "%target%"'
|
||||
invalidNumber: '&cUngültige Nummer: "%target%"'
|
||||
invalidPlayer: '&cSpieler nicht gefunden.'
|
||||
permissionOpenSelf: '&cDu darfst dein eigenes Inventar nicht öffnen.'
|
||||
permissionEnderAll: '&cDu darfst die Endertruhen von anderen Spielern nicht öffnen.'
|
||||
permissionExempt: '&c%target%''s Inventar ist geschützt.'
|
||||
permissionCrossWorld: '&c%target% ist nicht in der selben Welt wie du.'
|
||||
permissionPlayerOnline: '&cDu darfst keine Inventare von Spielern öffnen, die online sind.'
|
||||
permissionPlayerOffline: '&cDu darfst keine Inventare von Spielern öffnen, die offline sind.'
|
||||
commandException: '&cAn error occurred. Please check console for details.'
|
||||
info:
|
||||
containerBlocked: 'Du öffnest einen gesperrten Container.'
|
||||
containerBlockedSilent: 'Du öffnest einen gesperrten Container lautlos.'
|
||||
containerSilent: 'Du öffnest einen Container lautlos.'
|
||||
settingState: '%setting%: %state%'
|
||||
player:
|
||||
noMatches: 'Keine Spieler mit %target% gefunden.'
|
||||
matches: 'Spieler hält %target%: %detail%'
|
||||
container:
|
||||
noMatches: 'Keine Container mit %target% gefunden.'
|
||||
matches: 'Container hat %target%: %detail%'
|
||||
on: 'an'
|
||||
off: 'aus'
|
||||
container:
|
||||
player: '%player%''s Inventar'
|
||||
enderchest: '%player%''s Endertruhe'
|
30
plugin/src/main/resources/en_us.yml
Normal file
30
plugin/src/main/resources/en_us.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
messages:
|
||||
error:
|
||||
consoleUnsupported: 'You cannot use this command from console.'
|
||||
lootNotGenerated: '&cLoot not generated! Please disable &b/silentcontainer&c.'
|
||||
invalidMaterial: '&cInvalid material: "%target%"'
|
||||
invalidNumber: '&cInvalid number: "%target%"'
|
||||
invalidPlayer: '&cPlayer not found!'
|
||||
permissionOpenSelf: '&cYou''re not allowed to open your own inventory.'
|
||||
permissionEnderAll: '&cYou''re not allowed to access other players'' ender chests.'
|
||||
permissionExempt: '&c%target%''s inventory is protected.'
|
||||
permissionCrossWorld: '&c%target% is not in your world.'
|
||||
permissionPlayerOnline: '&cYou''re not allowed to open the inventory of online players.'
|
||||
permissionPlayerOffline: '&cYou''re not allowed to open the inventory of offline players.'
|
||||
commandException: '&cAn error occurred. Please check console for details.'
|
||||
info:
|
||||
containerBlocked: 'You are opening a blocked container.'
|
||||
containerBlockedSilent: 'You are opening a blocked container silently.'
|
||||
containerSilent: 'You are opening a container silently.'
|
||||
settingState: '%setting%: %state%'
|
||||
player:
|
||||
noMatches: 'No players found with %target%.'
|
||||
matches: 'Players holding %target%: %detail%'
|
||||
container:
|
||||
noMatches: 'No containers found with %target%.'
|
||||
matches: 'Containers holding %target%: %detail%'
|
||||
on: 'on'
|
||||
off: 'off'
|
||||
container:
|
||||
player: '%player%''s Inventory'
|
||||
enderchest: '%player%''s Ender Chest'
|
31
plugin/src/main/resources/es_es.yml
Normal file
31
plugin/src/main/resources/es_es.yml
Normal file
|
@ -0,0 +1,31 @@
|
|||
messages:
|
||||
error:
|
||||
consoleUnsupported: 'No puedes usar este comando desde la consola.'
|
||||
lootNotGenerated: '&c¡Botín no generado! Desactiva &b/silentcontainer&c.'
|
||||
invalidMaterial: '&cMaterial no válido: "%target%"'
|
||||
invalidNumber: '&cNúmero no válido: "%target%"'
|
||||
invalidPlayer: '&cJugador no encontrado'
|
||||
permissionOpenSelf: '&cNo tienes permisos para abrir tu inventario de esa forma.'
|
||||
permissionEnderAll: '&cNo tienes permiso para abrir cofres de ender de otros jugadores.'
|
||||
permissionExempt: '&c El inventario de %target% está protegido.'
|
||||
permissionCrossWorld: '&c%target% no está en tu dimensión.'
|
||||
permissionPlayerOnline: '&cNo estás autorizado para abrir inventarios de jugadores conectados.'
|
||||
permissionPlayerOffline: '&cNo estás autorizado para abrir inventarios de jugadores desconectados.'
|
||||
commandException: '&cSe ha producido un error, lee la consola para mas información.'
|
||||
info:
|
||||
containerBlocked: 'Estás abriendo un contenedor protegido.'
|
||||
containerBlockedSilent: 'Estás abriendo sigilosamente un contenedor protegido.'
|
||||
containerSilent: 'Estás abriendo un contenedor sigilosamente.'
|
||||
settingState: '%setting%: %state%'
|
||||
player:
|
||||
noMatches: 'No se encontraron jugadores con %target%.'
|
||||
matches: 'Jugadores con %target%: %detail%'
|
||||
container:
|
||||
noMatches: 'No se encontraron contenedores con %target%.'
|
||||
matches: 'Contenedores con %target%: %detail%'
|
||||
on: 'activado'
|
||||
off: 'desactivado'
|
||||
container:
|
||||
player: 'Inventario de %player%'
|
||||
enderchest: 'Cofre de Ender de %player%'
|
||||
|
|
@ -5,6 +5,7 @@ author: lishid
|
|||
authors: [Jikoo, ShadowRanger]
|
||||
description: >
|
||||
This plugin allows you to open a player's inventory as a chest and interact with it in real time.
|
||||
api-version: "1.16"
|
||||
|
||||
permissions:
|
||||
OpenInv.any.default:
|
||||
|
@ -13,47 +14,76 @@ permissions:
|
|||
OpenInv.silent.default:
|
||||
description: Permission for SilentContainer to default on prior to toggling.
|
||||
default: false
|
||||
OpenInv.*:
|
||||
description: Permission for all OpenInv features.
|
||||
default: op
|
||||
children:
|
||||
OpenInv.openinv: true
|
||||
OpenInv.openender: true
|
||||
OpenInv.search: true
|
||||
OpenInv.silent: true
|
||||
OpenInv.anychest: true
|
||||
OpenInv.searchenchant: true
|
||||
OpenInv.searchcontainer: true
|
||||
OpenInv.openonline: true
|
||||
OpenInv.openoffline: true
|
||||
OpenInv.spectate: true
|
||||
OpenInv.openinv:
|
||||
default: op
|
||||
children:
|
||||
OpenInv.openonline: true
|
||||
OpenInv.openoffline: true
|
||||
OpenInv.openender:
|
||||
default: op
|
||||
children:
|
||||
OpenInv.openonline: true
|
||||
OpenInv.openoffline: true
|
||||
|
||||
commands:
|
||||
openinv:
|
||||
aliases: [oi, inv, open]
|
||||
description: Open a player's inventory
|
||||
permission: OpenInv.*;OpenInv.openinv
|
||||
permission: OpenInv.openinv
|
||||
usage: |-
|
||||
/<command> [Player] - Open a player's inventory
|
||||
openender:
|
||||
aliases: [oe]
|
||||
description: Opens the enderchest of a player
|
||||
permission: OpenInv.*;OpenInv.openender
|
||||
permission: OpenInv.openender
|
||||
usage: |-
|
||||
/<command> [Player] - Open a player's enderchest
|
||||
searchinv:
|
||||
aliases: [si]
|
||||
description: Search and list players having a specific item
|
||||
permission: OpenInv.*;OpenInv.search
|
||||
permission: OpenInv.search
|
||||
usage: |-
|
||||
/<command> <Item> [MinAmount] - Item is the ID or the Bukkit Material, MinAmount is the minimum amount required
|
||||
/<command> <Material> [MinAmount] - MinAmount is optional, the minimum amount required
|
||||
searchender:
|
||||
aliases: [se]
|
||||
permission: OpenInv.*;OpenInv.search
|
||||
permission: OpenInv.search
|
||||
description: Searches and lists players having a specific item in their ender chest
|
||||
usage: |-
|
||||
/<command> <item> [MinAmount] - Item is the ID or the Bukkit Material, MinAmount is the minimum amount required
|
||||
/<command> <Material> [MinAmount] - MinAmount is optional, the minimum amount required
|
||||
silentcontainer:
|
||||
aliases: [sc, silent, silentchest]
|
||||
description: Toggle SilentContainer function, which stops sounds and animations when using containers.
|
||||
permission: OpenInv.*;OpenInv.silent
|
||||
description: SilentContainer stops sounds and animations when using containers.
|
||||
permission: OpenInv.silent
|
||||
usage: |-
|
||||
/<command> [Check] - Check or toggle silent chest
|
||||
/<command> [check|on|off] - Check, toggle, or set SilentContainer
|
||||
anycontainer:
|
||||
aliases: [ac, anychest]
|
||||
description: Toggle AnyContainer function, which allows opening of blocked containers.
|
||||
permission: OpenInv.*;OpenInv.anychest
|
||||
description: AnyContainer allows using blocked containers.
|
||||
permission: OpenInv.anychest
|
||||
usage: |-
|
||||
/<command> [Check] - Checks or toggle anychest
|
||||
/<command> [check|on|off] - Check, toggle, or set AnyContainer
|
||||
searchenchant:
|
||||
aliases: [searchenchants]
|
||||
description: Search and list players with a specific enchantment.
|
||||
permission: OpenInv.*;OpenInv.searchenchant
|
||||
permission: OpenInv.searchenchant
|
||||
usage: |-
|
||||
/<command> <[enchantment] [MinLevel]> - Enchantment is the enchantment type, MinLevel is the minimum level. One is optional
|
||||
/<command> <[Enchantment] [MinLevel]> - Enchantment is the enchantment type, MinLevel is the minimum level. One is optional
|
||||
searchcontainer:
|
||||
aliases: [searchchest]
|
||||
description: Search and list containers with a specific material.
|
||||
permission: OpenInv.searchcontainer
|
||||
usage: /<command> <Material> [ChunkRadius] - ChunkRadius is optional, the length that will be searched for matching items. Default 5
|
||||
|
|
30
plugin/src/main/resources/pt_br.yml
Normal file
30
plugin/src/main/resources/pt_br.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
messages:
|
||||
error:
|
||||
consoleUnsupported: 'Voce nao consegue usar esse comando pelo console.'
|
||||
lootNotGenerated: '&cPilhagem nao gerada! Por favor desabilite &b/silentcontainer&c.'
|
||||
invalidMaterial: '&cMaterial invalido: "%target%"'
|
||||
invalidNumber: '&cNumero invalido: "%target%"'
|
||||
invalidPlayer: '&cJogador nao encontrado!'
|
||||
permissionOpenSelf: '&cVoce nao pode abrir seu proprio inventario.'
|
||||
permissionEnderAll: '&cVoce nao tem permissao para abrir baus de ender de outros jogadores.'
|
||||
permissionExempt: '&cO inventario de %target% e protegido.'
|
||||
permissionCrossWorld: '&c%target% nao esta no seu mundo.'
|
||||
permissionPlayerOnline: '&cVoce nao tem permissao para abrir o inventario de jogadores online.'
|
||||
permissionPlayerOffline: '&cVoce nao tem permissao para abrir o inventario de jogadores offline.'
|
||||
commandException: '&cUm erro ocorreu. Por favor cheque o console para detalhes.'
|
||||
info:
|
||||
containerBlocked: 'Voce esta abrindo um recipiente bloqueado.'
|
||||
containerBlockedSilent: 'Voce esta abrindo um recipiente bloqueado silenciosamente.'
|
||||
containerSilent: 'Voce esta abrindo um recipiente silenciosamente.'
|
||||
settingState: '%setting%: %state%'
|
||||
player:
|
||||
noMatches: 'Nenhum jogador encontrado com %target%.'
|
||||
matches: 'Jogadores segurando %target%: %detail%'
|
||||
container:
|
||||
noMatches: 'Nenhum recipiente encontrado com %target%.'
|
||||
matches: 'Recipientes contendo %target%: %detail%'
|
||||
on: 'ligado'
|
||||
off: 'desligado'
|
||||
container:
|
||||
player: 'Inventario de %player%'
|
||||
enderchest: 'Bau de Ender de %player%'
|
27
pom.xml
27
pom.xml
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright (C) 2011-2018 lishid. All rights reserved.
|
||||
~ Copyright (C) 2011-2020 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
|
||||
|
@ -21,7 +21,7 @@
|
|||
<artifactId>openinvparent</artifactId>
|
||||
<name>OpenInvParent</name>
|
||||
<url>http://dev.bukkit.org/bukkit-plugins/openinv/</url>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.5-TF</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
|||
|
||||
<modules>
|
||||
<module>api</module>
|
||||
<module>common</module>
|
||||
<module>plugin</module>
|
||||
<module>internal</module>
|
||||
<module>assembly</module>
|
||||
|
@ -55,26 +54,6 @@
|
|||
</activation>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>latest</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>latest</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>recent</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>recent</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<repositories>
|
||||
|
@ -89,7 +68,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<filters>
|
||||
<filter>
|
||||
|
|
67
scripts/generate_changelog.sh
Normal file
67
scripts/generate_changelog.sh
Normal file
|
@ -0,0 +1,67 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# A script for generating a changelog from Git.
|
||||
#
|
||||
# Note that this script is designed for use in GitHub Actions, and is not
|
||||
# particularly robust nor configurable. Run from project parent directory.
|
||||
|
||||
# Query GitHub for the username of the given email address.
|
||||
# Falls through to the given author name.
|
||||
lookup_email_username() {
|
||||
lookup=$(curl -G --data-urlencode "q=$1 in:email" https://api.github.com/search/users -H 'Accept: application/vnd.github.v3+json' | grep '"login":' | sed -e 's/^.*": "//g' -e 's/",.*$//g')
|
||||
|
||||
if [[ $lookup ]]; then
|
||||
echo -n "@$lookup"
|
||||
else
|
||||
echo "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
# Use formatted log to pull authors list
|
||||
authors_raw=$(git log --pretty=format:"%ae|%an" "$(git describe --tags --abbrev=0 @^)"..@)
|
||||
readarray -t authors <<<"$authors_raw"
|
||||
|
||||
declare -A author_data
|
||||
|
||||
for author in "${authors[@]}"; do
|
||||
# Match author email
|
||||
author_email=${author%|*}
|
||||
# Convert to lower case
|
||||
author_email=${author_email,,}
|
||||
# Match author name
|
||||
author_name=${author##*|}
|
||||
if [[ -n ${author_data[$author_email]} ]]; then
|
||||
# Skip emails we already have data for
|
||||
continue
|
||||
fi
|
||||
|
||||
# Fetch and store author GitHub username by email
|
||||
author_data[$author_email]=$(lookup_email_username "$author_email" "$author_name")
|
||||
done
|
||||
|
||||
# Fetch actual formatted changelog
|
||||
changelog=$(git log --pretty=format:"%s (%h) - %ae" "$(git describe --tags --abbrev=0 @^)"..@)
|
||||
|
||||
for author_email in "${!author_data[@]}"; do
|
||||
# Ignore case when matching
|
||||
shopt -s nocasematch
|
||||
# Match and replace email
|
||||
changelog=${changelog//$author_email/${author_data[$author_email]}}
|
||||
done
|
||||
|
||||
echo "GENERATED_CHANGELOG<<EOF${changelog}EOF" >> "$GITHUB_ENV"
|
75
scripts/install_spigot_dependencies.sh
Normal file
75
scripts/install_spigot_dependencies.sh
Normal file
|
@ -0,0 +1,75 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# A script for installing required Spigot versions.
|
||||
#
|
||||
# Note that this script is designed for use in GitHub Actions, and is
|
||||
# not particularly robust nor configurable.
|
||||
# In its current state, the script must be run from OpenInv's parent
|
||||
# project directory and will always install BuildTools to ~/buildtools.
|
||||
|
||||
buildtools_dir=~/buildtools
|
||||
buildtools=$buildtools_dir/BuildTools.jar
|
||||
|
||||
get_spigot_versions () {
|
||||
# Get all submodules of internal module
|
||||
modules=$(mvn help:evaluate -Dexpression=project.modules -q -DforceStdout -P all -pl internal | grep -oP '(?<=<string>)(.*)(?=<\/string>)')
|
||||
for module in "${modules[@]}"; do
|
||||
|
||||
# Get number of dependencies declared in pom of specified internal module
|
||||
max_index=$(mvn help:evaluate -Dexpression=project.dependencies -q -DforceStdout -P all -pl internal/"$module" | grep -c "<dependency>")
|
||||
|
||||
for ((i=0; i < max_index; i++)); do
|
||||
# Get artifactId of dependency
|
||||
artifact_id=$(mvn help:evaluate -Dexpression=project.dependencies["$i"].artifactId -q -DforceStdout -P all -pl internal/"$module")
|
||||
|
||||
# Ensure dependency is spigot
|
||||
if [[ "$artifact_id" == spigot ]]; then
|
||||
# Get spigot version
|
||||
spigot_version=$(mvn help:evaluate -Dexpression=project.dependencies["$i"].version -q -DforceStdout -P all -pl internal/"$module")
|
||||
echo "$spigot_version"
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
get_buildtools () {
|
||||
if [[ -d $buildtools_dir && -f $buildtools ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
mkdir $buildtools_dir
|
||||
wget https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar -O $buildtools
|
||||
}
|
||||
|
||||
versions=$(get_spigot_versions)
|
||||
echo Found Spigot dependencies: "$versions"
|
||||
|
||||
for version in "${versions[@]}"; do
|
||||
set -e
|
||||
exit_code=0
|
||||
mvn dependency:get -Dartifact=org.spigotmc:spigot:"$version" -q -o || exit_code=$?
|
||||
if [ $exit_code -ne 0 ]; then
|
||||
echo Installing missing Spigot version "$version"
|
||||
revision=$(echo "$version" | grep -oP '(\d+\.\d+(\.\d+)?)(?=-R[0-9\.]+-SNAPSHOT)')
|
||||
get_buildtools
|
||||
java -jar $buildtools -rev "$revision"
|
||||
else
|
||||
echo Spigot "$version" is already installed
|
||||
fi
|
||||
done
|
Loading…
Reference in a new issue