add item commands
This commit is contained in:
339
LICENSE
Normal file
339
LICENSE
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
48
README.md
Normal file
48
README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# BedwarsXP
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
BedwarsXP - BedwarsRel addon (A Minecraft Server Plugin)
|
||||
|
||||
BedwarsRel起床战争小游戏插件的经验起床Addon
|
||||
|
||||
## 功能特性
|
||||
|
||||
- **经验经济系统**:将 BedwarsRel 的资源经济转换为经验值经济
|
||||
- **资源兑换商店**:添加经验兑换分类,允许玩家将资源转换为经验
|
||||
- **命令商店物品支持**:支持配置执行命令的商店物品(如权限、传送等命令)
|
||||
- **全经验模式**:支持将所有商店物品转换为经验交易
|
||||
|
||||
## 最近更新
|
||||
|
||||
### 新增:命令商店物品支持
|
||||
|
||||
现在支持在商店中配置执行命令的物品,而非仅给予物品:
|
||||
|
||||
```yaml
|
||||
shop:
|
||||
- item1:
|
||||
type: EXP_BOTTLE
|
||||
amount: 10
|
||||
reward:
|
||||
type: STONE
|
||||
meta:
|
||||
==: ItemMeta
|
||||
meta-type: UNSPECIFIC
|
||||
display-name: §eVIP权限
|
||||
commands:
|
||||
- "lp user %player% parent add vip"
|
||||
```
|
||||
|
||||
- `%player%` 变量会被替换为购买玩家的名称
|
||||
- 支持 XP 交易和传统物品交易两种模式
|
||||
- 购买时会自动扣除相应的经验或资源
|
||||
|
||||
## 协议
|
||||
|
||||
本项目基于 [GPL-2.0](LICENSE) 协议开源。
|
||||
|
||||
> 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; either version 2 of the License, or
|
||||
> (at your option) any later version.
|
||||
96
dependency-reduced-pom.xml
Normal file
96
dependency-reduced-pom.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>sakura.kooi</groupId>
|
||||
<artifactId>BedwarsXP</artifactId>
|
||||
<version>2.1.3</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
<forceJavacCompilerUse>true</forceJavacCompilerUse>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>sakura.kooi.utils.lib.bstats</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.20</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<groupId>commons-lang</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>guava</artifactId>
|
||||
<groupId>com.google.guava</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<groupId>org.yaml</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>bungeecord-chat</artifactId>
|
||||
<groupId>net.md-5</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.bedwarsrel</groupId>
|
||||
<artifactId>BedwarsRel</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
87
pom.xml
Normal file
87
pom.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
|
||||
<groupId>sakura.kooi</groupId>
|
||||
<artifactId>BedwarsXP</artifactId>
|
||||
<version>2.1.3</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.20</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.bedwarsrel</groupId>
|
||||
<artifactId>BedwarsRel</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
<forceJavacCompilerUse>true</forceJavacCompilerUse>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.bstats</pattern>
|
||||
<shadedPattern>sakura.kooi.utils.lib.bstats</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
105
src/main/java/ldcr/BedwarsXP/BedwarsXP.java
Normal file
105
src/main/java/ldcr/BedwarsXP/BedwarsXP.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package ldcr.BedwarsXP;
|
||||
|
||||
import ldcr.BedwarsXP.command.BedwarsXPCommandListener;
|
||||
import ldcr.BedwarsXP.command.EditXPCommandListener;
|
||||
import ldcr.BedwarsXP.utils.ActionBarUtils;
|
||||
import ldcr.BedwarsXP.utils.ReflectionUtils;
|
||||
import lombok.Getter;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import sakura.kooi.utils.GithubUpdateChecker.UpdateChecker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BedwarsXP extends JavaPlugin {
|
||||
@Getter
|
||||
private static final Map<String, String> l18nCache = new HashMap<>();
|
||||
@Getter
|
||||
private static BedwarsXP instance;
|
||||
@Getter
|
||||
private static CommandSender consoleSender;
|
||||
@Getter
|
||||
private static String updateUrl = null;
|
||||
|
||||
public static String l18n(String key, String... replacement) {
|
||||
String message;
|
||||
if (l18nCache.containsKey(key)) {
|
||||
message = l18nCache.get(key);
|
||||
} else {
|
||||
message = Config.getLanguageYaml().getString(key, "LANG_NOT_FOUND_" + key);
|
||||
l18nCache.put(key, message);
|
||||
}
|
||||
for (int i = 0, length = replacement.length / 2; i < length; i++) {
|
||||
message = message.replace(replacement[i * 2], replacement[i * 2 + 1]);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public static void sendConsoleMessage(String str) {
|
||||
consoleSender.sendMessage("§6§lBedwarsXP §7>> " + str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
consoleSender = Bukkit.getConsoleSender();
|
||||
|
||||
try {
|
||||
sendConsoleMessage("§bLoading BedwarsXP... Version." + getDescription().getVersion());
|
||||
Config.loadConfig();
|
||||
if (!detectBedwarsRelVersion()) {
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
ActionBarUtils.load();
|
||||
Bukkit.getPluginManager().registerEvents(new EventListeners(), this);
|
||||
getCommand("bedwarsxp").setExecutor(new BedwarsXPCommandListener());
|
||||
getCommand("bedwarsxpedit").setExecutor(new EditXPCommandListener());
|
||||
} catch (Exception e) {
|
||||
sendConsoleMessage("§c§lERROR: §c-----------------------------------");
|
||||
e.printStackTrace();
|
||||
sendConsoleMessage("§c§lERROR: §c-----------------------------------");
|
||||
sendConsoleMessage("§c§lERROR: §c" + l18n("ERROR_OCCURRED_WHILE_LOADING"));
|
||||
sendConsoleMessage("§c§lERROR: §e ↓↓ << " + l18n("REPORT_ISSUE_HERE") + " >> ↓↓ ");
|
||||
sendConsoleMessage("§c§lERROR: §c https://github.com/SakuraKoi/BedwarsXP/issues/1");
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
return;
|
||||
}
|
||||
sendConsoleMessage("§b" + l18n("SUCCESSFULLY_LOADED") + " By.SakuraKooi");
|
||||
sendConsoleMessage("§e ↓↓ << " + l18n("REPORT_ISSUE_AND_SUGGESTION_HERE") + " >> ↓↓ ");
|
||||
sendConsoleMessage("§c https://github.com/SakuraKoi/BedwarsXP/issues/1");
|
||||
// Update checker and metrics
|
||||
if (!Config.disableUpdateChecker) {
|
||||
Bukkit.getScheduler().runTaskLater(this, () -> {
|
||||
try {
|
||||
new UpdateChecker("SakuraKoi", "BedwarsXP", "v" + getDescription().getVersion(), link -> {
|
||||
updateUrl = link;
|
||||
sendConsoleMessage("§b" + l18n("HAS_UPDATE", "%link%", link));
|
||||
}).check();
|
||||
} catch (IOException ignored) {}
|
||||
}, 100);
|
||||
}
|
||||
try {
|
||||
new Metrics(this, 3999);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
private boolean detectBedwarsRelVersion() {
|
||||
sendConsoleMessage("§a" + l18n("FINDING_BEDWARSREL"));
|
||||
if (ReflectionUtils.isClassFound("io.github.yannici.bedwars.Main") || ReflectionUtils.isClassFound("io.github.bedwarsrel.BedwarsRel.Main")) {
|
||||
sendConsoleMessage("§c" + l18n("BEDWARSREL_NOT_SUPPORTED"));
|
||||
sendConsoleMessage("§c" + l18n("PLEASE_UPDATE_BEDWARSREL"));
|
||||
return false;
|
||||
} else if (ReflectionUtils.isClassFound("io.github.bedwarsrel.BedwarsRel")) {
|
||||
sendConsoleMessage("§a" + l18n("BEDWARSREL_SUPPORTED"));
|
||||
return true;
|
||||
} else {
|
||||
sendConsoleMessage("§c§lERROR: §c" + l18n("BEDWARSREL_NOT_FOUND"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
145
src/main/java/ldcr/BedwarsXP/Config.java
Normal file
145
src/main/java/ldcr/BedwarsXP/Config.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package ldcr.BedwarsXP;
|
||||
|
||||
import ldcr.BedwarsXP.utils.YamlUtils;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
public class Config {
|
||||
public static final Map<Material, Integer> resources = new EnumMap<>(Material.class);
|
||||
public static final Set<String> resourceskey = new HashSet<>();
|
||||
private static final int CONFIG_VERSION = 2;
|
||||
private static final Set<String> enabledGameList = new HashSet<>();
|
||||
public static boolean disableUpdateChecker;
|
||||
|
||||
public static String xpMessage;
|
||||
public static boolean addResShop;
|
||||
|
||||
public static double deathCost;
|
||||
public static double deathDrop;
|
||||
public static boolean dontDropExpBottle;
|
||||
public static int maxXP;
|
||||
public static String maxXPMessage;
|
||||
|
||||
public static boolean fullXPBedwars;
|
||||
private static YamlConfiguration enabledGamesYaml;
|
||||
private static File enabledGamesFile;
|
||||
@Getter
|
||||
private static YamlConfiguration languageYaml;
|
||||
|
||||
public static void loadConfig() {
|
||||
BedwarsXP.sendConsoleMessage("§b正在加载语言文件... | Loading language configuration...");
|
||||
File languageFile = new File("plugins/BedwarsXP/language.yml");
|
||||
if (!languageFile.exists()) {
|
||||
BedwarsXP.sendConsoleMessage("§b语言文件不存在,正在创建...");
|
||||
BedwarsXP.sendConsoleMessage("§bWanna english? Just overwrites language.yml with language-en.yml :)");
|
||||
BedwarsXP.getInstance().saveResource("language.yml", true);
|
||||
BedwarsXP.getInstance().saveResource("language-en.yml", true);
|
||||
}
|
||||
try {
|
||||
languageYaml = YamlUtils.loadYamlUTF8(languageFile);
|
||||
} catch (IOException e) {
|
||||
languageYaml = new YamlConfiguration();
|
||||
BedwarsXP.sendConsoleMessage("§c语言文件加载失败 | Failed to load language");
|
||||
e.printStackTrace();
|
||||
}
|
||||
BedwarsXP.sendConsoleMessage("§b" + BedwarsXP.l18n("LOADING_CONFIGURATION"));
|
||||
File configFile = new File("plugins/BedwarsXP/config.yml");
|
||||
if (!configFile.exists()) {
|
||||
BedwarsXP.sendConsoleMessage("§b" + BedwarsXP.l18n("CONFIGURATION_FILE_NOT_EXISTS"));
|
||||
BedwarsXP.getInstance().saveResource("config.yml", true);
|
||||
}
|
||||
YamlConfiguration configYaml = YamlConfiguration.loadConfiguration(configFile);
|
||||
|
||||
if (configYaml.getInt("ConfigVersion") < CONFIG_VERSION) {
|
||||
BedwarsXP.sendConsoleMessage("§4" + BedwarsXP.l18n("OLD_VERSION_CONFIGURATION"));
|
||||
configFile.renameTo(new File("plugins/BedwarsXP/config.bak.yml"));
|
||||
BedwarsXP.sendConsoleMessage("§c" + BedwarsXP.l18n("OLD_CONFIGURATION_BACKUPED"));
|
||||
BedwarsXP.getInstance().saveResource("config.yml", true);
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("NEW_CONFIGURATION_SAVED"));
|
||||
configFile = new File("plugins/BedwarsXP/config.yml");
|
||||
configYaml = YamlConfiguration.loadConfiguration(configFile);
|
||||
}
|
||||
|
||||
disableUpdateChecker = configYaml.getBoolean("Disable_UpdateChecker", true);
|
||||
|
||||
xpMessage = configYaml.getString("Message").replaceAll("&", "§").replaceAll("§§", "§");
|
||||
addResShop = configYaml.getBoolean("Add_Res_Shop");
|
||||
if (addResShop) {
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("RESOURCE_SHOP_ENABLED"));
|
||||
}
|
||||
|
||||
deathCost = configYaml.getInt("DeathCostXP", 0) / 100.0;
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("DEATH_COST_XP_PERCENT", "%percent%", String.valueOf(deathCost * 100)));
|
||||
|
||||
deathDrop = configYaml.getInt("DeathDropXP", 0) / 100.0;
|
||||
BedwarsXP.sendConsoleMessage(
|
||||
"§6§lBedwarsXP §7>> §a" + (deathDrop == 0 ? BedwarsXP.l18n("DEATH_DROP_XP_DISABLED") : BedwarsXP.l18n("DEATH_DROP_XP_PERCEMT", "%percent%", String.valueOf(deathDrop * 100))));
|
||||
dontDropExpBottle = configYaml.getBoolean("DontDropExpBottle", false);
|
||||
if (dontDropExpBottle)
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("DEATH_DROP_EXP_BOTTLE_DISABLED"));
|
||||
|
||||
maxXP = configYaml.getInt("MaxXP");
|
||||
maxXPMessage = configYaml.getString("MaxXPMessage").replaceAll("&", "§").replaceAll("§§", "§");
|
||||
BedwarsXP.sendConsoleMessage("§a" + (maxXP == 0 ? BedwarsXP.l18n("MAX_XP_LIMIT_DISABLED") : BedwarsXP.l18n("MAX_XP_LIMIT_ENABLED", "%value%", String.valueOf(maxXP))));
|
||||
|
||||
fullXPBedwars = configYaml.getBoolean("Full_XP_Bedwars");
|
||||
if (fullXPBedwars) {
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("ALL_TRADES_USE_XP_ENABLED"));
|
||||
}
|
||||
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("LOADING_RESOURCES_VALUE"));
|
||||
ConfigurationSection resourceSection = io.github.bedwarsrel.BedwarsRel.getInstance().getConfig()
|
||||
.getConfigurationSection("resource");
|
||||
for (String key : resourceSection.getKeys(false)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> resourceList = (List<Map<String, Object>>) io.github.bedwarsrel.BedwarsRel
|
||||
.getInstance().getConfig().getList("resource." + key + ".item");
|
||||
for (Map<String, Object> resource : resourceList) {
|
||||
ItemStack itemStack = ItemStack.deserialize(resource);
|
||||
Material mat = itemStack.getType();
|
||||
int xp = configYaml.getInt("XP." + key, 0);
|
||||
resources.put(mat, xp);
|
||||
resourceskey.add(key);
|
||||
BedwarsXP.sendConsoleMessage("§a" + BedwarsXP.l18n("FOUNDED_RESOURCE",
|
||||
"%resource%", key,
|
||||
"%material%", mat.toString(),
|
||||
"%value%", String.valueOf(xp)));
|
||||
}
|
||||
}
|
||||
|
||||
enabledGamesFile = new File("plugins/BedwarsXP/enabledGames.yml");
|
||||
if (!enabledGamesFile.exists()) {
|
||||
BedwarsXP.sendConsoleMessage("§c" + BedwarsXP.l18n("WARN_YOU_NEEDS_ENABLE_BEDWARSXP_MANUALLY"));
|
||||
BedwarsXP.getInstance().saveResource("enabledGames.yml", true);
|
||||
}
|
||||
enabledGamesYaml = YamlConfiguration.loadConfiguration(enabledGamesFile);
|
||||
enabledGameList.addAll(enabledGamesYaml.getStringList("enabledGame"));
|
||||
}
|
||||
|
||||
public static String setGameEnableXP(String bw, boolean isEnabled) {
|
||||
if (isEnabled) {
|
||||
enabledGameList.add(bw);
|
||||
} else {
|
||||
enabledGameList.remove(bw);
|
||||
}
|
||||
enabledGamesYaml.set("enabledGame", new ArrayList<>(enabledGameList));
|
||||
try {
|
||||
enabledGamesYaml.save(enabledGamesFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return e.getLocalizedMessage();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static boolean isGameEnabledXP(String bw) {
|
||||
return enabledGameList.contains(bw);
|
||||
}
|
||||
}
|
||||
208
src/main/java/ldcr/BedwarsXP/EventListeners.java
Normal file
208
src/main/java/ldcr/BedwarsXP/EventListeners.java
Normal file
@@ -0,0 +1,208 @@
|
||||
package ldcr.BedwarsXP;
|
||||
|
||||
import io.github.bedwarsrel.BedwarsRel;
|
||||
import io.github.bedwarsrel.events.BedwarsGameEndEvent;
|
||||
import io.github.bedwarsrel.events.BedwarsGameStartEvent;
|
||||
import io.github.bedwarsrel.game.Game;
|
||||
import ldcr.BedwarsXP.XPShop.ShopReplacer;
|
||||
import ldcr.BedwarsXP.api.XPManager;
|
||||
import ldcr.BedwarsXP.api.events.BedwarsXPDeathDropXPEvent;
|
||||
import ldcr.BedwarsXP.utils.ResourceUtils;
|
||||
import ldcr.BedwarsXP.utils.SoundMachine;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class EventListeners implements Listener {
|
||||
@SuppressWarnings("deprecation")
|
||||
@EventHandler
|
||||
public void onItemPickup(PlayerPickupItemEvent e) {
|
||||
Player p = e.getPlayer();
|
||||
Game bw = checkGame(p);
|
||||
if (bw == null) return;
|
||||
|
||||
Item entity = e.getItem();
|
||||
ItemStack stack = entity.getItemStack();
|
||||
if (stack == null) return;
|
||||
Integer count;
|
||||
if (stack.hasItemMeta() && stack.getItemMeta().getDisplayName() != null && stack.getItemMeta().getDisplayName().equals("§b§l&BedwarsXP_DroppedXP")) {
|
||||
count = Integer.parseInt(stack.getItemMeta().getLore().get(0));
|
||||
} else {
|
||||
count = ResourceUtils.convertResToXP(stack);
|
||||
}
|
||||
|
||||
if (count == null)
|
||||
return;
|
||||
|
||||
if (pickupXP(bw, p, count)) {
|
||||
e.setCancelled(true);
|
||||
entity.remove();
|
||||
} else {
|
||||
e.setCancelled(true);
|
||||
entity.setPickupDelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean pickupXP(Game bw, Player player, int count) {
|
||||
if (count <= 0) return true;
|
||||
|
||||
XPManager xpman = XPManager.getXPManager(bw.getName());
|
||||
// if current XP > maxXP -> deny pickup
|
||||
if (Config.maxXP != 0 && xpman.getXP(player) >= Config.maxXP) {
|
||||
xpman.sendMaxXPMessage(player);
|
||||
return false;
|
||||
}
|
||||
int added = xpman.getXP(player) + count;
|
||||
int leftXP = 0;
|
||||
// if after pickup XP>maxXP -> set XP = maxXP
|
||||
if (Config.maxXP != 0 && added > Config.maxXP) {
|
||||
leftXP = added - Config.maxXP;
|
||||
added = Config.maxXP;
|
||||
}
|
||||
xpman.setXP(player, added);
|
||||
player.playSound(player.getLocation(), SoundMachine.get("ORB_PICKUP", "ENTITY_EXPERIENCE_ORB_PICKUP"), 0.2F, 1.5F);
|
||||
xpman.sendXPMessage(player, count);
|
||||
if (leftXP > 0) {
|
||||
dropXPBottle(player, leftXP);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void dropXPBottle(Player player, int xp) {
|
||||
ItemStack dropStack = new ItemStack(Material.EXP_BOTTLE, 16);
|
||||
ItemMeta meta = dropStack.getItemMeta();
|
||||
meta.setDisplayName("§b§l&BedwarsXP_DroppedXP");
|
||||
meta.setLore(Collections.singletonList(String.valueOf(xp)));
|
||||
meta.addEnchant(Enchantment.LOOT_BONUS_MOBS, 1, true);
|
||||
dropStack.setItemMeta(meta);
|
||||
Item droppedItem = player.getWorld().dropItemNaturally(player.getLocation().add(0, 1, 0), dropStack);
|
||||
droppedItem.setPickupDelay(40);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onAnvilOpen(InventoryOpenEvent e) {
|
||||
if (e.getPlayer() == null)
|
||||
return;
|
||||
if (e.getInventory() == null)
|
||||
return;
|
||||
Game bw = checkGame((Player) e.getPlayer());
|
||||
if (bw == null) return;
|
||||
if (e.getInventory().getType().equals(InventoryType.ANVIL)) {
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerDeath(PlayerDeathEvent e) {
|
||||
Player p = e.getEntity();
|
||||
Game bw = checkGame(p);
|
||||
if (bw == null) return;
|
||||
|
||||
XPManager xpman = XPManager.getXPManager(bw.getName());
|
||||
// 计算死亡扣除经验值
|
||||
int costed = (int) (xpman.getXP(p) * Config.deathCost);
|
||||
// 计算死亡掉落经验值
|
||||
int dropped = 0;
|
||||
if (Config.deathDrop > 0) {
|
||||
dropped = (int) (costed * Config.deathDrop);
|
||||
}
|
||||
BedwarsXPDeathDropXPEvent event = new BedwarsXPDeathDropXPEvent(bw.getName(), p, dropped, costed);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
costed = event.getXPCost();
|
||||
dropped = event.getXPDropped();
|
||||
// 扣除经验
|
||||
int to = xpman.getXP(p) - costed;
|
||||
if (to < 0) {
|
||||
to = 0;
|
||||
}
|
||||
e.setNewLevel(to);
|
||||
xpman.setXP(p, to);
|
||||
// 掉落经验
|
||||
if (dropped < 1)
|
||||
return;
|
||||
if (Config.dontDropExpBottle) {
|
||||
EntityDamageEvent ev = p.getLastDamageCause();
|
||||
if (ev instanceof EntityDamageByEntityEvent) {
|
||||
Object killer = ((EntityDamageByEntityEvent) ev).getDamager();
|
||||
if (killer instanceof Projectile) {
|
||||
killer = ((Projectile) killer).getShooter();
|
||||
}
|
||||
if (killer instanceof Player) {
|
||||
pickupXP(bw, (Player) killer, dropped);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
dropXPBottle(p, dropped);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBedWarsStart(BedwarsGameStartEvent e) {
|
||||
if (e.isCancelled())
|
||||
return;
|
||||
if (!Config.isGameEnabledXP(e.getGame().getName()))
|
||||
return;
|
||||
ShopReplacer.replaceShop(e.getGame().getName(), BedwarsXP.getConsoleSender());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onBedWarsEnd(BedwarsGameEndEvent e) {
|
||||
if (!Config.isGameEnabledXP(e.getGame().getName()))
|
||||
return;
|
||||
XPManager.reset(e.getGame().getName());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerTeleport(PlayerTeleportEvent e) { // 在玩家传送后更新经验条
|
||||
Player p = e.getPlayer();
|
||||
Game bw = checkGame(p);
|
||||
if (bw == null) return;
|
||||
Bukkit.getScheduler().runTaskLater(BedwarsXP.getInstance(),
|
||||
() -> XPManager.getXPManager(bw.getName()).updateXPBar(p), 5);
|
||||
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent e) {
|
||||
Game bw = checkGame(e.getPlayer());
|
||||
if (bw == null) return;
|
||||
XPManager.getXPManager(bw.getName()).updateXPBar(e.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent e) {
|
||||
if (BedwarsXP.getUpdateUrl() != null && e.getPlayer().hasPermission("bedwarsxp.admin")) {
|
||||
Bukkit.getScheduler().runTaskLater(BedwarsXP.getInstance(), () -> {
|
||||
if (e.getPlayer().isOnline())
|
||||
e.getPlayer().sendMessage("§6§lBedwarsXP §7>> §b" + BedwarsXP.l18n("HAS_UPDATE", "%link%", BedwarsXP.getUpdateUrl()));
|
||||
}, 30);
|
||||
}
|
||||
}
|
||||
|
||||
private Game checkGame(Player player) {
|
||||
Game bw = BedwarsRel.getInstance().getGameManager().getGameOfPlayer(player);
|
||||
if (bw == null)
|
||||
return null;
|
||||
if (!Config.isGameEnabledXP(bw.getName()))
|
||||
return null;
|
||||
return bw;
|
||||
}
|
||||
}
|
||||
102
src/main/java/ldcr/BedwarsXP/XPShop/ShopReplacer.java
Normal file
102
src/main/java/ldcr/BedwarsXP/XPShop/ShopReplacer.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package ldcr.BedwarsXP.XPShop;
|
||||
|
||||
import io.github.bedwarsrel.BedwarsRel;
|
||||
import io.github.bedwarsrel.game.Game;
|
||||
import io.github.bedwarsrel.shop.NewItemShop;
|
||||
import io.github.bedwarsrel.villager.MerchantCategory;
|
||||
import io.github.bedwarsrel.villager.MerchantCategoryComparator;
|
||||
import io.github.bedwarsrel.villager.VillagerTrade;
|
||||
import ldcr.BedwarsXP.BedwarsXP;
|
||||
import ldcr.BedwarsXP.Config;
|
||||
import ldcr.BedwarsXP.utils.ReflectionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ShopReplacer implements Runnable {
|
||||
private final Game game;
|
||||
private final CommandSender s;
|
||||
|
||||
private ShopReplacer(String e, CommandSender sender) {
|
||||
s = sender;
|
||||
game = BedwarsRel.getInstance().getGameManager().getGame(e);
|
||||
}
|
||||
|
||||
public static void replaceShop(String bw, CommandSender sender) {
|
||||
if (!Config.isGameEnabledXP(bw))
|
||||
return;
|
||||
Bukkit.getScheduler().runTaskLater(BedwarsXP.getInstance(), new ShopReplacer(bw, sender), 20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
HashMap<Material, MerchantCategory> map = game.getItemShopCategories();
|
||||
if (Config.fullXPBedwars) {
|
||||
for (Entry<Material, MerchantCategory> en : map.entrySet()) {
|
||||
MerchantCategory m = en.getValue();
|
||||
ArrayList<VillagerTrade> t = m.getOffers();
|
||||
ArrayList<XPVillagerTrade> n = new ArrayList<>();
|
||||
for (VillagerTrade villagerTrade : t) {
|
||||
if (villagerTrade == null)
|
||||
continue;
|
||||
n.add(new XPVillagerTrade(villagerTrade));
|
||||
}
|
||||
try {
|
||||
ReflectionUtils.setPrivateValue(m, "offers", n);
|
||||
} catch (Exception e1) {
|
||||
s.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("ERROR_OCCURRED_REPLACE_SHOP", "%game%", game.getName()));
|
||||
e1.printStackTrace();
|
||||
}
|
||||
map.put(en.getKey(), m);
|
||||
}
|
||||
}
|
||||
if (Config.addResShop) {
|
||||
ArrayList<VillagerTrade> trades = new ArrayList<>();
|
||||
for (String key : Config.resourceskey) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> resourceList = (List<Map<String, Object>>) io.github.bedwarsrel.BedwarsRel.getInstance().getConfig().getList("resource." + key + ".item");
|
||||
for (Map<String, Object> resource : resourceList) {
|
||||
ItemStack itemStack = ItemStack.deserialize(resource);
|
||||
if (itemStack != null) {
|
||||
trades.add(new XPVillagerTrade(itemStack));
|
||||
}
|
||||
}
|
||||
}
|
||||
MerchantCategory mc = new MerchantCategory(BedwarsXP.l18n("SHOP_XP_EXCHANGE_TITLE"), Material.EXP_BOTTLE, trades, Collections.singletonList(BedwarsXP.l18n("SHOP_XP_EXCHANGE_LORE")), 3, "bw.base");
|
||||
map.put(Material.EXP_BOTTLE, mc);
|
||||
}
|
||||
// 检查并显示带命令的物品数量
|
||||
int commandItems = 0;
|
||||
for (MerchantCategory cat : map.values()) {
|
||||
for (VillagerTrade trade : cat.getOffers()) {
|
||||
if (trade.hasCommands()) {
|
||||
commandItems++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commandItems > 0) {
|
||||
s.sendMessage("§6§lBedwarsXP §7>> §a检测到 " + commandItems + " 个命令商店物品");
|
||||
}
|
||||
try {
|
||||
Field itemshops = ReflectionUtils.getField(game, "newItemShops");
|
||||
itemshops.setAccessible(true);
|
||||
HashMap<Player, NewItemShop> shops = new HashMap<>();
|
||||
List<MerchantCategory> order = new ArrayList<>(map.values());
|
||||
order.sort(new MerchantCategoryComparator());
|
||||
for (Player pl : game.getPlayers()) {
|
||||
shops.put(pl, new XPItemShop(order, game));
|
||||
}
|
||||
ReflectionUtils.setPrivateValue(game, "newItemShops", shops);
|
||||
s.sendMessage("§6§lBedwarsXP §7>> §b" + BedwarsXP.l18n("SUCCESSFULLY_REPLACED_SHOP", "%game%", game.getName()));
|
||||
} catch (Exception e) {
|
||||
s.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("ERROR_OCCURRED_WHILE_INITALIZING_XP_SHOP", "%game%", game.getName()));
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
502
src/main/java/ldcr/BedwarsXP/XPShop/XPItemShop.java
Normal file
502
src/main/java/ldcr/BedwarsXP/XPShop/XPItemShop.java
Normal file
@@ -0,0 +1,502 @@
|
||||
package ldcr.BedwarsXP.XPShop;
|
||||
|
||||
import io.github.bedwarsrel.BedwarsRel;
|
||||
import io.github.bedwarsrel.game.Game;
|
||||
import io.github.bedwarsrel.shop.NewItemShop;
|
||||
import io.github.bedwarsrel.utils.ChatWriter;
|
||||
import io.github.bedwarsrel.utils.Utils;
|
||||
import io.github.bedwarsrel.villager.MerchantCategory;
|
||||
import io.github.bedwarsrel.villager.VillagerTrade;
|
||||
import ldcr.BedwarsXP.BedwarsXP;
|
||||
import ldcr.BedwarsXP.api.XPManager;
|
||||
import ldcr.BedwarsXP.utils.SoundMachine;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class XPItemShop extends NewItemShop {
|
||||
private final Game bedwars;
|
||||
private final List<MerchantCategory> categories;
|
||||
private MerchantCategory currentCategory = null;
|
||||
XPItemShop(List<MerchantCategory> cate, Game bw) {
|
||||
super(cate);
|
||||
categories = cate;
|
||||
bedwars = bw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MerchantCategory> getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOpenCategory() {
|
||||
return currentCategory != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasOpenCategory(MerchantCategory category) {
|
||||
if (currentCategory == null)
|
||||
return false;
|
||||
|
||||
return currentCategory.equals(category);
|
||||
}
|
||||
|
||||
private int getCategoriesSize(Player player) {
|
||||
int size = 0;
|
||||
for (MerchantCategory cat : categories) {
|
||||
if (cat.getMaterial() != null && (player == null || player.hasPermission(cat.getPermission()))) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openCategoryInventory(Player player) {
|
||||
int catSize = getCategoriesSize(player);
|
||||
int nom = catSize % 9 == 0 ? 9 : catSize % 9;
|
||||
int size = catSize + 9 - nom + 9;
|
||||
|
||||
Inventory inventory = Bukkit.createInventory(player, size, BedwarsRel._l("ingame.shop.name"));
|
||||
|
||||
addCategoriesToInventory(inventory, player);
|
||||
|
||||
Game game = BedwarsRel.getInstance().getGameManager().getGameOfPlayer(player);
|
||||
ItemStack stack;
|
||||
|
||||
if (game != null) {
|
||||
if (game.getPlayerSettings(player).oneStackPerShift()) {
|
||||
stack = new ItemStack(Material.BUCKET, 1);
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
|
||||
meta.setDisplayName(ChatColor.AQUA + BedwarsRel._l("default.currently") + ": " + ChatColor.WHITE + BedwarsRel._l("ingame.shop.onestackpershift"));
|
||||
|
||||
meta.setLore(new ArrayList<>());
|
||||
stack.setItemMeta(meta);
|
||||
} else {
|
||||
stack = new ItemStack(Material.LAVA_BUCKET, 1);
|
||||
ItemMeta meta = stack.getItemMeta();
|
||||
|
||||
meta.setDisplayName(ChatColor.AQUA + BedwarsRel._l("default.currently") + ": " + ChatColor.WHITE + BedwarsRel._l("ingame.shop.fullstackpershift"));
|
||||
|
||||
meta.setLore(new ArrayList<>());
|
||||
stack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
inventory.setItem(size - 4, stack);
|
||||
}
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
|
||||
private void addCategoriesToInventory(Inventory inventory, Player player) {
|
||||
for (MerchantCategory category : categories) {
|
||||
if (category.getMaterial() == null) {
|
||||
BedwarsRel.getInstance().getServer().getConsoleSender().sendMessage(ChatWriter.pluginMessage(ChatColor.RED + "Careful: Not supported material in shop category '" + category.getName() + "'"));
|
||||
} else if (player == null || player.hasPermission(category.getPermission())) {
|
||||
ItemStack is = new ItemStack(category.getMaterial(), 1);
|
||||
ItemMeta im = is.getItemMeta();
|
||||
|
||||
if (currentCategory != null && currentCategory.equals(category)) {
|
||||
im.addEnchant(Enchantment.DAMAGE_ALL, 1, true);
|
||||
}
|
||||
|
||||
im.setDisplayName(category.getName());
|
||||
im.setLore(category.getLores());
|
||||
is.setItemMeta(im);
|
||||
|
||||
inventory.addItem(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getInventorySize(int itemAmount) {
|
||||
int nom = itemAmount % 9 == 0 ? 9 : itemAmount % 9;
|
||||
return itemAmount + 9 - nom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInventoryClick(InventoryClickEvent ice, Game game, Player player) {
|
||||
if (!hasOpenCategory()) {
|
||||
handleCategoryInventoryClick(ice, game, player);
|
||||
} else {
|
||||
handleBuyInventoryClick(ice, game, player);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCategoryInventoryClick(InventoryClickEvent ice, Game game, Player player) {
|
||||
int catSize = getCategoriesSize(player);
|
||||
int sizeCategories = getInventorySize(catSize) + 9;
|
||||
int rawSlot = ice.getRawSlot();
|
||||
|
||||
if (rawSlot >= getInventorySize(catSize) && rawSlot < sizeCategories) {
|
||||
ice.setCancelled(true);
|
||||
|
||||
if (ice.getCurrentItem().getType() == Material.BUCKET) {
|
||||
game.getPlayerSettings(player).setOneStackPerShift(false);
|
||||
player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), 10.0F, 1.0F);
|
||||
openCategoryInventory(player);
|
||||
return;
|
||||
}
|
||||
if (ice.getCurrentItem().getType() == Material.LAVA_BUCKET) {
|
||||
game.getPlayerSettings(player).setOneStackPerShift(true);
|
||||
player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), 10.0F, 1.0F);
|
||||
openCategoryInventory(player);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (rawSlot >= sizeCategories) {
|
||||
if (ice.isShiftClick()) {
|
||||
ice.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
ice.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
MerchantCategory clickedCategory = getCategoryByMaterial(ice.getCurrentItem().getType());
|
||||
if (clickedCategory == null) {
|
||||
if (ice.isShiftClick()) {
|
||||
ice.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
ice.setCancelled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
openBuyInventory(clickedCategory, player, game);
|
||||
}
|
||||
|
||||
private void openBuyInventory(MerchantCategory category, Player player, Game game) {
|
||||
ArrayList<VillagerTrade> offers = category.getOffers();
|
||||
int sizeCategories = getCategoriesSize(player);
|
||||
int sizeItems = offers.size();
|
||||
int invSize = getBuyInventorySize(sizeCategories, sizeItems);
|
||||
|
||||
player.playSound(player.getLocation(), SoundMachine.get("CLICK", "UI_BUTTON_CLICK"), 10.0F, 1.0F);
|
||||
|
||||
currentCategory = category;
|
||||
Inventory buyInventory = Bukkit.createInventory(player, invSize, BedwarsRel._l("ingame.shop.name"));
|
||||
addCategoriesToInventory(buyInventory, player);
|
||||
|
||||
for (int i = 0; i < offers.size(); i++) {
|
||||
VillagerTrade trade = offers.get(i);
|
||||
if (trade.getItem1().getType() != Material.AIR || trade.getRewardItem().getType() != Material.AIR) {
|
||||
int slot = getInventorySize(sizeCategories) + i;
|
||||
ItemStack tradeStack = toItemStack(trade, player, game);
|
||||
|
||||
buyInventory.setItem(slot, tradeStack);
|
||||
}
|
||||
}
|
||||
player.openInventory(buyInventory);
|
||||
}
|
||||
|
||||
private int getBuyInventorySize(int sizeCategories, int sizeOffers) {
|
||||
return getInventorySize(sizeCategories) + getInventorySize(sizeOffers);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private ItemStack toItemStack(VillagerTrade trade, Player player, Game game) {
|
||||
ItemStack tradeStack = trade.getRewardItem().clone();
|
||||
Method colorable = Utils.getColorableMethod(tradeStack.getType());
|
||||
ItemMeta meta = tradeStack.getItemMeta();
|
||||
ItemStack item1 = trade.getItem1();
|
||||
ItemStack item2 = trade.getItem2();
|
||||
if (tradeStack.getType().equals(Material.STAINED_GLASS) || tradeStack.getType().equals(Material.WOOL) || tradeStack.getType().equals(Material.STAINED_CLAY)) {
|
||||
tradeStack.setDurability(game.getPlayerTeam(player).getColor().getDyeColor().getWoolData());
|
||||
} else if (colorable != null) {
|
||||
colorable.setAccessible(true);
|
||||
try {
|
||||
colorable.invoke(meta, game.getPlayerTeam(player).getColor().getColor());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
List<String> lores = meta.getLore();
|
||||
if (lores == null) {
|
||||
lores = new ArrayList<>();
|
||||
}
|
||||
if (trade instanceof XPVillagerTrade) {
|
||||
lores.add(BedwarsXP.l18n("SHOP_TRADE_XP", "%xp%", String.valueOf(((XPVillagerTrade) trade).getXp())));
|
||||
} else {
|
||||
lores.add(ChatColor.WHITE + String.valueOf(item1.getAmount()) + " " + item1.getItemMeta().getDisplayName());
|
||||
if (item2 != null) {
|
||||
lores.add(ChatColor.WHITE + String.valueOf(item2.getAmount()) + " " + item2.getItemMeta().getDisplayName());
|
||||
}
|
||||
}
|
||||
meta.setLore(lores);
|
||||
tradeStack.setItemMeta(meta);
|
||||
return tradeStack;
|
||||
}
|
||||
|
||||
private void handleBuyInventoryClick(InventoryClickEvent ice, Game game, Player player) {
|
||||
int sizeCategories = getCategoriesSize(player);
|
||||
ArrayList<VillagerTrade> offers = currentCategory.getOffers();
|
||||
int sizeItems = offers.size();
|
||||
int totalSize = getBuyInventorySize(sizeCategories, sizeItems);
|
||||
|
||||
ItemStack item = ice.getCurrentItem();
|
||||
boolean cancel = false;
|
||||
int bought = 0;
|
||||
boolean oneStackPerShift = game.getPlayerSettings(player).oneStackPerShift();
|
||||
|
||||
if (currentCategory == null) {
|
||||
player.closeInventory();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ice.getRawSlot() < sizeCategories) {
|
||||
ice.setCancelled(true);
|
||||
|
||||
if (item == null)
|
||||
return;
|
||||
if (item.getType().equals(currentCategory.getMaterial())) {
|
||||
currentCategory = null;
|
||||
openCategoryInventory(player);
|
||||
} else {
|
||||
handleCategoryInventoryClick(ice, game, player);
|
||||
}
|
||||
} else if (ice.getRawSlot() < totalSize) {
|
||||
ice.setCancelled(true);
|
||||
|
||||
if (item == null || item.getType() == Material.AIR)
|
||||
return;
|
||||
|
||||
MerchantCategory category = currentCategory;
|
||||
VillagerTrade trade = getTradingItem(category, item, game, player);
|
||||
|
||||
if (trade == null) {
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] getTradingItem returned null!");
|
||||
return;
|
||||
}
|
||||
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] getTradingItem returned trade: " + trade.getClass().getName());
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] trade.hasCommands in handleBuy: " + trade.hasCommands());
|
||||
if (trade.getRewardItem() != null) {
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] reward item: " + trade.getRewardItem().getType());
|
||||
}
|
||||
|
||||
player.playSound(player.getLocation(), SoundMachine.get("ITEM_PICKUP", "ENTITY_ITEM_PICKUP"), 10.0F, 1.0F);
|
||||
|
||||
if (!hasEnoughRessource(player, trade)) {
|
||||
player.sendMessage(ChatWriter.pluginMessage(ChatColor.RED + BedwarsRel._l("errors.notenoughress")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ice.isShiftClick()) {
|
||||
while (hasEnoughRessource(player, trade) && !cancel) {
|
||||
cancel = !buyItem(trade, ice.getCurrentItem(), player);
|
||||
if (!cancel && oneStackPerShift) {
|
||||
bought += item.getAmount();
|
||||
cancel = bought + item.getAmount() > 64;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buyItem(trade, ice.getCurrentItem(), player);
|
||||
}
|
||||
} else {
|
||||
ice.setCancelled(ice.isShiftClick());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean buyItem(VillagerTrade trade, ItemStack item, Player player) {
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
boolean success = true;
|
||||
|
||||
// 调试输出
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] buyItem called, trade class: " + trade.getClass().getName());
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] trade.hasCommands(): " + trade.hasCommands());
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] trade.getCommands(): " + trade.getCommands());
|
||||
|
||||
// 检查是否有命令,如果有则执行命令而不是给予物品
|
||||
if (trade.hasCommands()) {
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop] 执行命令物品,玩家: " + player.getName() + ", 命令数: " + trade.getCommands().size());
|
||||
if (!(trade instanceof XPVillagerTrade)) {
|
||||
// 非XP trade 扣除物品
|
||||
int item1ToPay = trade.getItem1().getAmount();
|
||||
Iterator<?> stackIterator = inventory.all(trade.getItem1().getType()).entrySet().iterator();
|
||||
int firstItem1 = inventory.first(trade.getItem1());
|
||||
takeItem(inventory, item1ToPay, stackIterator, firstItem1);
|
||||
if (trade.getItem2() != null) {
|
||||
int item2ToPay = trade.getItem2().getAmount();
|
||||
stackIterator = inventory.all(trade.getItem2().getType()).entrySet().iterator();
|
||||
int firstItem2 = inventory.first(trade.getItem2());
|
||||
takeItem(inventory, item2ToPay, stackIterator, firstItem2);
|
||||
}
|
||||
} else {
|
||||
// XP trade 扣除经验
|
||||
XPManager.getXPManager(bedwars.getName()).takeXP(player, ((XPVillagerTrade) trade).getXp());
|
||||
}
|
||||
// 执行命令
|
||||
for (String command : trade.getCommands()) {
|
||||
String formattedCommand = command.replace("%player%", player.getName());
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop] 执行命令: " + formattedCommand);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), formattedCommand);
|
||||
}
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop] 命令执行完成");
|
||||
return success;
|
||||
}
|
||||
|
||||
// 没有命令,正常给予物品
|
||||
if (!(trade instanceof XPVillagerTrade)) {
|
||||
// 非XPtrade 使用旧式购买
|
||||
int item1ToPay = trade.getItem1().getAmount();
|
||||
Iterator<?> stackIterator = inventory.all(trade.getItem1().getType()).entrySet().iterator();
|
||||
int firstItem1 = inventory.first(trade.getItem1());
|
||||
takeItem(inventory, item1ToPay, stackIterator, firstItem1);
|
||||
if (trade.getItem2() != null) {
|
||||
int item2ToPay = trade.getItem2().getAmount();
|
||||
stackIterator = inventory.all(trade.getItem2().getType()).entrySet().iterator();
|
||||
|
||||
int firstItem2 = inventory.first(trade.getItem2());
|
||||
takeItem(inventory, item2ToPay, stackIterator, firstItem2);
|
||||
}
|
||||
} else {
|
||||
// Already checked has enough XP
|
||||
XPManager.getXPManager(bedwars.getName()).takeXP(player, ((XPVillagerTrade) trade).getXp());
|
||||
}
|
||||
ItemStack addingItem = item.clone();
|
||||
ItemMeta meta = addingItem.getItemMeta();
|
||||
List<String> lore = meta.getLore();
|
||||
|
||||
if (!lore.isEmpty()) {
|
||||
lore.remove(lore.size() - 1);
|
||||
if (trade.getItem2() != null && !(trade instanceof XPVillagerTrade)) {
|
||||
lore.remove(lore.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
meta.setLore(lore);
|
||||
addingItem.setItemMeta(meta);
|
||||
|
||||
HashMap<Integer, ? extends ItemStack> notStored = inventory.addItem(addingItem);
|
||||
if (notStored.size() > 0) {
|
||||
ItemStack notAddedItem = notStored.get(0);
|
||||
int removingAmount = addingItem.getAmount() - notAddedItem.getAmount();
|
||||
addingItem.setAmount(removingAmount);
|
||||
inventory.removeItem(addingItem);
|
||||
|
||||
inventory.addItem(trade.getItem1());
|
||||
if (trade.getItem2() != null) {
|
||||
inventory.addItem(trade.getItem2());
|
||||
}
|
||||
|
||||
success = false;
|
||||
}
|
||||
|
||||
player.updateInventory();
|
||||
return success;
|
||||
}
|
||||
|
||||
private void takeItem(PlayerInventory inventory, int item1ToPay, Iterator<?> stackIterator, int firstItem1) {
|
||||
if (firstItem1 > -1) {
|
||||
inventory.clear(firstItem1);
|
||||
} else {
|
||||
while (stackIterator.hasNext()) {
|
||||
Entry<?, ?> entry = (Entry<?, ?>) stackIterator.next();
|
||||
ItemStack stack = (ItemStack) entry.getValue();
|
||||
|
||||
int endAmount = stack.getAmount() - item1ToPay;
|
||||
if (endAmount < 0) {
|
||||
endAmount = 0;
|
||||
}
|
||||
|
||||
item1ToPay -= stack.getAmount();
|
||||
stack.setAmount(endAmount);
|
||||
inventory.setItem((Integer) entry.getKey(), stack);
|
||||
|
||||
if (item1ToPay <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasEnoughRessource(Player player, VillagerTrade trade) {
|
||||
if (trade instanceof XPVillagerTrade)
|
||||
return XPManager.getXPManager(bedwars.getName()).hasEnoughXP(player, ((XPVillagerTrade) trade).getXp());
|
||||
else {
|
||||
ItemStack item1 = trade.getItem1();
|
||||
ItemStack item2 = trade.getItem2();
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
|
||||
if (item2 != null) {
|
||||
return inventory.contains(item1.getType(), item1.getAmount()) && inventory.contains(item2.getType(), item2.getAmount());
|
||||
} else return inventory.contains(item1.getType(), item1.getAmount());
|
||||
}
|
||||
}
|
||||
|
||||
private VillagerTrade getTradingItem(MerchantCategory category, ItemStack stack, Game game, Player player) {
|
||||
for (VillagerTrade trade : category.getOffers()) {
|
||||
if (trade.getItem1().getType() != Material.AIR || trade.getRewardItem().getType() != Material.AIR) {
|
||||
// 获取原始 reward 物品(不经过 toItemStack 处理)
|
||||
ItemStack reward = trade.getRewardItem();
|
||||
|
||||
// 首先比较类型
|
||||
if (reward.getType() != stack.getType()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 对于末影箱特殊处理
|
||||
if (reward.getType() == Material.ENDER_CHEST && stack.getType() == Material.ENDER_CHEST)
|
||||
return trade;
|
||||
|
||||
// 对于药水类特殊处理
|
||||
if (reward.getType() == Material.POTION ||
|
||||
(!BedwarsRel.getInstance().getCurrentVersion().startsWith("v1_9") &&
|
||||
(reward.getType().equals(Material.valueOf("TIPPED_ARROW")) ||
|
||||
reward.getType().equals(Material.valueOf("LINGERING_POTION")) ||
|
||||
reward.getType().equals(Material.valueOf("SPLASH_POTION"))))) {
|
||||
if (((PotionMeta) reward.getItemMeta()).getCustomEffects().equals(((PotionMeta) stack.getItemMeta()).getCustomEffects()))
|
||||
return trade;
|
||||
}
|
||||
|
||||
// 对于普通物品,比较显示名
|
||||
ItemMeta rewardMeta = reward.getItemMeta();
|
||||
ItemMeta stackMeta = stack.getItemMeta();
|
||||
String rewardName = rewardMeta != null ? rewardMeta.getDisplayName() : null;
|
||||
String stackName = stackMeta != null ? stackMeta.getDisplayName() : null;
|
||||
|
||||
if ((rewardName == null && stackName == null) ||
|
||||
(rewardName != null && rewardName.equals(stackName))) {
|
||||
Bukkit.getConsoleSender().sendMessage("[BW-XP-Shop-DEBUG] Matched trade: name=" + rewardName + ", hasCommands=" + trade.hasCommands());
|
||||
return trade;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private MerchantCategory getCategoryByMaterial(Material material) {
|
||||
for (MerchantCategory category : categories) {
|
||||
if (category.getMaterial() == material)
|
||||
return category;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentCategory(MerchantCategory category) {
|
||||
currentCategory = category;
|
||||
}
|
||||
}
|
||||
46
src/main/java/ldcr/BedwarsXP/XPShop/XPVillagerTrade.java
Normal file
46
src/main/java/ldcr/BedwarsXP/XPShop/XPVillagerTrade.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package ldcr.BedwarsXP.XPShop;
|
||||
|
||||
import io.github.bedwarsrel.villager.VillagerTrade;
|
||||
import ldcr.BedwarsXP.utils.ResourceUtils;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class XPVillagerTrade extends VillagerTrade {
|
||||
@Setter
|
||||
private int xp = 0;
|
||||
|
||||
public XPVillagerTrade(VillagerTrade t) {
|
||||
super(t.getItem1(), t.getItem2(), t.getRewardItem(), t.getCommands());
|
||||
setXp(ResourceUtils.convertResToXPExact(t.getItem1()) + ResourceUtils.convertResToXPExact(t.getItem2()));
|
||||
}
|
||||
|
||||
public XPVillagerTrade(ItemStack convert) {
|
||||
super(convert, null, convert);
|
||||
setXp(ResourceUtils.convertResToXP(convert));
|
||||
}
|
||||
|
||||
public XPVillagerTrade(int xp, ItemStack rewardItem) {
|
||||
super(new ItemStack(Material.EXP_BOTTLE, xp), rewardItem);
|
||||
setXp(xp);
|
||||
}
|
||||
|
||||
public XPVillagerTrade(int xp, ItemStack rewardItem, List<String> commands) {
|
||||
super(new ItemStack(Material.EXP_BOTTLE, xp), rewardItem, commands);
|
||||
setXp(xp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated It will be removed in later version, use getXp() instead
|
||||
*/
|
||||
@Deprecated
|
||||
public int getXP() {
|
||||
return this.xp;
|
||||
}
|
||||
|
||||
public int getXp() {
|
||||
return this.xp;
|
||||
}
|
||||
}
|
||||
92
src/main/java/ldcr/BedwarsXP/api/XPManager.java
Normal file
92
src/main/java/ldcr/BedwarsXP/api/XPManager.java
Normal file
@@ -0,0 +1,92 @@
|
||||
package ldcr.BedwarsXP.api;
|
||||
|
||||
import ldcr.BedwarsXP.Config;
|
||||
import ldcr.BedwarsXP.utils.ActionBarUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class XPManager {
|
||||
private static final Map<String, XPManager> managerMap = new HashMap<>();
|
||||
private final Map<UUID, Integer> xp = new HashMap<>();
|
||||
private final HashMap<UUID, Long> messageTimeMap = new HashMap<>();
|
||||
private final HashMap<UUID, Integer> messageCountMap = new HashMap<>();
|
||||
|
||||
public static XPManager getXPManager(String bedwarsGame) {
|
||||
if (!managerMap.containsKey(bedwarsGame)) {
|
||||
managerMap.put(bedwarsGame, new XPManager());
|
||||
}
|
||||
return managerMap.get(bedwarsGame);
|
||||
}
|
||||
|
||||
public static void reset(String bedwarsGame) {
|
||||
managerMap.remove(bedwarsGame);
|
||||
}
|
||||
|
||||
public void updateXPBar(Player player) {
|
||||
player.setLevel(get(player));
|
||||
}
|
||||
|
||||
private void set(Player player, int count) {
|
||||
xp.put(player.getUniqueId(), count);
|
||||
updateXPBar(player);
|
||||
}
|
||||
|
||||
private int get(Player player) {
|
||||
Integer value = xp.get(player.getUniqueId());
|
||||
if (value == null) {
|
||||
value = 0;
|
||||
xp.put(player.getUniqueId(), 0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setXP(Player player, int count) {
|
||||
set(player, count);
|
||||
}
|
||||
|
||||
public int getXP(Player player) {
|
||||
return get(player);
|
||||
}
|
||||
|
||||
public void addXP(Player player, int count) {
|
||||
set(player, get(player) + count);
|
||||
}
|
||||
|
||||
public boolean takeXP(Player player, int count) {
|
||||
if (!hasEnoughXP(player, count))
|
||||
return false;
|
||||
set(player, get(player) - count);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasEnoughXP(Player player, int count) {
|
||||
return get(player) >= count;
|
||||
}
|
||||
|
||||
public void sendXPMessage(Player player, int count) {
|
||||
if (!messageTimeMap.containsKey(player.getUniqueId())) {
|
||||
messageTimeMap.put(player.getUniqueId(), System.currentTimeMillis());
|
||||
}
|
||||
if (!messageCountMap.containsKey(player.getUniqueId())) {
|
||||
messageCountMap.put(player.getUniqueId(), 0);
|
||||
}
|
||||
if (System.currentTimeMillis() - messageTimeMap.get(player.getUniqueId()) > 500) {
|
||||
messageCountMap.put(player.getUniqueId(), 0);
|
||||
}
|
||||
messageTimeMap.put(player.getUniqueId(), System.currentTimeMillis());
|
||||
int c = messageCountMap.get(player.getUniqueId()) + count;
|
||||
messageCountMap.put(player.getUniqueId(), c);
|
||||
if (!Config.xpMessage.isEmpty()) {
|
||||
ActionBarUtils.sendActionBar(player, Config.xpMessage.replaceAll("%xp%", Integer.toString(c)));
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMaxXPMessage(Player player) {
|
||||
if (!Config.maxXPMessage.isEmpty()) {
|
||||
ActionBarUtils.sendActionBar(player, Config.maxXPMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package ldcr.BedwarsXP.api.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class BedwarsXPDeathDropXPEvent extends Event {
|
||||
private final String game;
|
||||
private final Player player;
|
||||
private int deathCost;
|
||||
private int deathDropped;
|
||||
public BedwarsXPDeathDropXPEvent(String game, Player p, int dropped, int cost) {
|
||||
this.game = game;
|
||||
player = p;
|
||||
deathCost = cost;
|
||||
deathDropped = dropped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return new HandlerList();
|
||||
}
|
||||
|
||||
public String getGameName() {
|
||||
return game;
|
||||
}
|
||||
|
||||
public Player getDeadPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public int getXPCost() {
|
||||
return deathCost;
|
||||
}
|
||||
|
||||
public void setXPCost(int drop) {
|
||||
deathCost = drop;
|
||||
}
|
||||
|
||||
public int getXPDropped() {
|
||||
return deathDropped;
|
||||
}
|
||||
|
||||
public void setXPDropped(int deathDropped) {
|
||||
this.deathDropped = deathDropped;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getXPCosted() {
|
||||
return deathCost;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setXPCosted(int drop) {
|
||||
deathCost = drop;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package ldcr.BedwarsXP.command;
|
||||
|
||||
import ldcr.BedwarsXP.BedwarsXP;
|
||||
import ldcr.BedwarsXP.Config;
|
||||
import ldcr.BedwarsXP.utils.BedwarsGameUtils;
|
||||
import ldcr.BedwarsXP.utils.SendMessageUtils;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class BedwarsXPCommandListener implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) {
|
||||
if (args.length == 0) {
|
||||
SendMessageUtils.sendMessage(sender,
|
||||
"§6§lBedwarsXP §7>> §bBedwarsXP v." + BedwarsXP.getInstance().getDescription().getVersion() + " §lBy.SakuraKooi",
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_RELOAD"),
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_ENABLE"),
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_DISABLE"));
|
||||
return true;
|
||||
}
|
||||
if (!sender.hasPermission("bedwarsxp.admin")) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("YOU_DONT_HAVE_PERMISSION_TO_EXECUTE_THIS_COMMAND"));
|
||||
return true;
|
||||
}
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "reload": {
|
||||
Config.loadConfig();
|
||||
BedwarsXP.getL18nCache().clear();
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §b" + BedwarsXP.l18n("SUCCESSFULLY_RELOADED"));
|
||||
if (BedwarsGameUtils.isAnyBedwarsRunning()) {
|
||||
SendMessageUtils.sendMessage(sender,
|
||||
"§6§lBedwarsXP §7>> §b" + BedwarsXP.l18n("RELOAD_GAME_RUNNING"),
|
||||
"§6§lBedwarsXP §7>> §b" + BedwarsXP.l18n("UPDATE_RUNNING_GAME"));
|
||||
BedwarsGameUtils.replaceAllShop(sender);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "enable": {
|
||||
if (args.length != 2) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_ENABLE"));
|
||||
return true;
|
||||
}
|
||||
if (!BedwarsGameUtils.isGameExists(args[1])) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("ERROR_GAME_NOT_FOUND", "%game%", args[1]));
|
||||
return true;
|
||||
}
|
||||
String result = Config.setGameEnableXP(args[1], true);
|
||||
if (result.equals("")) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("GAME_XP_ENABLED", "%game%", args[1]));
|
||||
if (BedwarsGameUtils.isGameRunning(args[1])) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §4" + BedwarsXP.l18n("GAME_IS_RUNNING_RESTART_REQUIRED", "%game%", args[1]));
|
||||
}
|
||||
} else {
|
||||
SendMessageUtils.sendMessage(sender, "§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("ERROR_OCCURRED"), "§6§lBedwarsXP §7>> §c" + result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case "disable": {
|
||||
if (args.length != 2) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_DISABLE"));
|
||||
return true;
|
||||
}
|
||||
if (!BedwarsGameUtils.isGameExists(args[1])) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("ERROR_GAME_NOT_FOUND", "%game%", args[1]));
|
||||
return true;
|
||||
}
|
||||
String result = Config.setGameEnableXP(args[1], false);
|
||||
if (result.equals("")) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("GAME_XP_DISABLED", "%game%", args[1]));
|
||||
if (BedwarsGameUtils.isGameRunning(args[1])) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §4" + BedwarsXP.l18n("GAME_IS_RUNNING_RESTART_REQUIRED", "%game%", args[1]));
|
||||
}
|
||||
} else {
|
||||
SendMessageUtils.sendMessage(sender, "§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("ERROR_OCCURRED"), "§6§lBedwarsXP §7>> §c" + result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
SendMessageUtils.sendMessage(sender,
|
||||
"§6§lBedwarsXP §7>> §bBedwarsXP v." + BedwarsXP.getInstance().getDescription().getVersion() + " §lBy.SakuraKooi",
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_RELOAD"),
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_ENABLE"),
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_MAIN_DISABLE"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package ldcr.BedwarsXP.command;
|
||||
|
||||
import io.github.bedwarsrel.BedwarsRel;
|
||||
import io.github.bedwarsrel.game.Game;
|
||||
import ldcr.BedwarsXP.BedwarsXP;
|
||||
import ldcr.BedwarsXP.Config;
|
||||
import ldcr.BedwarsXP.api.XPManager;
|
||||
import ldcr.BedwarsXP.utils.SendMessageUtils;
|
||||
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.entity.Player;
|
||||
|
||||
public class EditXPCommandListener implements CommandExecutor {
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command arg1, String arg2, String[] args) {
|
||||
if (args.length < 3) {
|
||||
SendMessageUtils.sendMessage(sender,
|
||||
"§6§lBedwarsXP §7>> §bBedwarsXP v." + BedwarsXP.getInstance().getDescription().getVersion() + " §lBy.SakuraKooi",
|
||||
"§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("HELP_EDITXP"));
|
||||
return true;
|
||||
}
|
||||
if (!sender.hasPermission("bedwarsxp.admin")) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("YOU_DONT_HAVE_PERMISSION_TO_EXECUTE_THIS_COMMAND"));
|
||||
return true;
|
||||
}
|
||||
String user = args[1];
|
||||
OfflinePlayer offPlayer = Bukkit.getPlayer(user);
|
||||
if (offPlayer != null) {
|
||||
if (offPlayer.isOnline()) {
|
||||
Player p = offPlayer.getPlayer();
|
||||
Game bw = BedwarsRel.getInstance().getGameManager().getGameOfPlayer(p);
|
||||
if (bw == null) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("EDITXP_PLAYER_NOT_IN_GAME", "%player%", p.getName()));
|
||||
return true;
|
||||
}
|
||||
if (!Config.isGameEnabledXP(bw.getName())) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("EDITXP_GAME_IS_NOT_XP_MODE", "%player%", p.getName()));
|
||||
return true;
|
||||
}
|
||||
int xp;
|
||||
try {
|
||||
xp = Integer.parseInt(args[2]);
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("EDITXP_XP_IS_NOT_A_NUMBER"));
|
||||
return true;
|
||||
}
|
||||
if ("set".equalsIgnoreCase(args[0])) {
|
||||
XPManager.getXPManager(bw.getName()).setXP(p, xp);
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("EDITXP_XP_HAS_BEEN_SET_TO", "%player%", p.getName(), "%xp%", String.valueOf(xp)));
|
||||
} else if ("add".equalsIgnoreCase(args[0])) {
|
||||
int current = XPManager.getXPManager(bw.getName()).getXP(p);
|
||||
XPManager.getXPManager(bw.getName()).setXP(p, current + xp);
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("EDITXP_XP_HAS_BEEN_SET_TO", "%player%", p.getName(), "%xp%", String.valueOf(current + xp)));
|
||||
} else if ("take".equalsIgnoreCase(args[0])) {
|
||||
int current = XPManager.getXPManager(bw.getName()).getXP(p);
|
||||
XPManager.getXPManager(bw.getName()).setXP(p, current - xp);
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §a" + BedwarsXP.l18n("EDITXP_XP_HAS_BEEN_SET_TO", "%player%", p.getName(), "%xp%", String.valueOf(current - xp)));
|
||||
} else {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("HELP_EDITXP"));
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("EDITXP_PLAYER_NOT_IN_GAME", "%player%", offPlayer.getName()));
|
||||
}
|
||||
} else {
|
||||
sender.sendMessage("§6§lBedwarsXP §7>> §c" + BedwarsXP.l18n("EDITXP_PLAYER_NOT_IN_GAME", "%player%", args[1]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
108
src/main/java/ldcr/BedwarsXP/utils/ActionBarUtils.java
Normal file
108
src/main/java/ldcr/BedwarsXP/utils/ActionBarUtils.java
Normal file
@@ -0,0 +1,108 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import ldcr.BedwarsXP.BedwarsXP;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ActionBarUtils {
|
||||
private static boolean USE_CHAT = false;
|
||||
private static boolean USE_1_7_NMS = false;
|
||||
private static boolean USE_1_8_NMS = false;
|
||||
private static boolean USE_1_11_API = false;
|
||||
|
||||
private static Class<?> classCraftPlayer;
|
||||
private static Class<?> classPacketPlayOutChat;
|
||||
private static Class<?> classPacket;
|
||||
private static Class<?> classChatSerializer;
|
||||
private static Method methodSerializeMessage;
|
||||
private static Class<?> classIChatBaseComponent;
|
||||
private static Class<?> classChatComponentText;
|
||||
private static Method methodGetHandle = null;
|
||||
private static Field fieldPlayerConnection = null;
|
||||
private static Method methodSendPacket = null;
|
||||
|
||||
public static void load() {
|
||||
String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName();
|
||||
NMS_VERSION = NMS_VERSION.substring(NMS_VERSION.lastIndexOf('.') + 1);
|
||||
|
||||
if (NMS_VERSION.equalsIgnoreCase("v1_8_R1") || NMS_VERSION.equalsIgnoreCase("v1_7_")) {
|
||||
USE_1_7_NMS = true;
|
||||
} else {
|
||||
try {
|
||||
int ver = Integer.parseInt(NMS_VERSION.split("_")[1]);
|
||||
if (ver >= 11) {
|
||||
USE_1_11_API = true;
|
||||
} else {
|
||||
USE_1_8_NMS = true;
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
|
||||
BedwarsXP.sendConsoleMessage("§cERROR: " + BedwarsXP.l18n("ERROR_UNSUPPORTED_VERSION_ACTIONBAR_MAY_NOT_WORK"));
|
||||
USE_CHAT = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_1_7_NMS || USE_1_8_NMS) {
|
||||
try {
|
||||
classCraftPlayer = Class.forName("org.bukkit.craftbukkit." + NMS_VERSION + ".entity.CraftPlayer");
|
||||
classPacketPlayOutChat = Class.forName("net.minecraft.server." + NMS_VERSION + ".PacketPlayOutChat");
|
||||
classIChatBaseComponent = Class.forName("net.minecraft.server." + NMS_VERSION + ".IChatBaseComponent");
|
||||
classPacket = Class.forName("net.minecraft.server." + NMS_VERSION + ".Packet");
|
||||
if (USE_1_7_NMS) {
|
||||
classChatSerializer = Class.forName("net.minecraft.server." + NMS_VERSION + ".ChatSerializer");
|
||||
methodSerializeMessage = classChatSerializer.getDeclaredMethod("a", String.class);
|
||||
} else {
|
||||
classChatComponentText = Class.forName("net.minecraft.server." + NMS_VERSION + ".ChatComponentText");
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
BedwarsXP.sendConsoleMessage("§cERROR: " + BedwarsXP.l18n("ERROR_UNSUPPORTED_VERSION_ACTIONBAR_MAY_NOT_WORK"));
|
||||
USE_1_7_NMS = false;
|
||||
USE_1_8_NMS = false;
|
||||
USE_CHAT = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendActionBar(Player player, String message) {
|
||||
if (USE_CHAT) {
|
||||
player.sendMessage(message);
|
||||
} else if (USE_1_11_API) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message));
|
||||
} else if (USE_1_7_NMS || USE_1_8_NMS) {
|
||||
try {
|
||||
Object objectCraftPlayer = classCraftPlayer.cast(player);
|
||||
Object objectPacketChat;
|
||||
Object objectChatComponent;
|
||||
if (USE_1_7_NMS) {
|
||||
objectChatComponent = classIChatBaseComponent.cast(methodSerializeMessage.invoke(classChatSerializer, "{\"text\": \"" + message + "\"}"));
|
||||
} else {
|
||||
objectChatComponent = classChatComponentText.getConstructor(String.class).newInstance(message);
|
||||
}
|
||||
objectPacketChat = classPacketPlayOutChat.getConstructor(classIChatBaseComponent, byte.class).newInstance(objectChatComponent, (byte) 2);
|
||||
if (methodGetHandle == null)
|
||||
methodGetHandle = classCraftPlayer.getDeclaredMethod("getHandle");
|
||||
Object objectEntityPlayer = methodGetHandle.invoke(objectCraftPlayer);
|
||||
if (fieldPlayerConnection == null)
|
||||
fieldPlayerConnection = objectEntityPlayer.getClass().getDeclaredField("playerConnection");
|
||||
Object objectPlayerConnection = fieldPlayerConnection.get(objectEntityPlayer);
|
||||
if (methodSendPacket == null)
|
||||
methodSendPacket = objectPlayerConnection.getClass().getDeclaredMethod("sendPacket", classPacket);
|
||||
methodSendPacket.invoke(objectPlayerConnection, objectPacketChat);
|
||||
} catch (ReflectiveOperationException e) { // Reflection exception caught -> dont retry, switch to backend
|
||||
e.printStackTrace();
|
||||
USE_1_7_NMS = false;
|
||||
USE_1_8_NMS = false;
|
||||
USE_CHAT = true;
|
||||
player.sendMessage(message);
|
||||
} catch (Exception e) { // send message to chat instead, retry actionbar later
|
||||
e.printStackTrace();
|
||||
player.sendMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
37
src/main/java/ldcr/BedwarsXP/utils/BedwarsGameUtils.java
Normal file
37
src/main/java/ldcr/BedwarsXP/utils/BedwarsGameUtils.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import io.github.bedwarsrel.BedwarsRel;
|
||||
import io.github.bedwarsrel.game.Game;
|
||||
import io.github.bedwarsrel.game.GameState;
|
||||
import ldcr.BedwarsXP.XPShop.ShopReplacer;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BedwarsGameUtils {
|
||||
public static boolean isGameExists(String bw) {
|
||||
return BedwarsRel.getInstance().getGameManager().getGame(bw) != null;
|
||||
}
|
||||
|
||||
public static boolean isGameRunning(String bw) {
|
||||
return BedwarsRel.getInstance().getGameManager().getGame(bw).getState().equals(GameState.RUNNING);
|
||||
}
|
||||
|
||||
public static boolean isAnyBedwarsRunning() {
|
||||
ArrayList<Game> bw = BedwarsRel.getInstance().getGameManager().getGames();
|
||||
for (Game game : bw) {
|
||||
if (game.getState().equals(GameState.RUNNING))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void replaceAllShop(CommandSender sender) {
|
||||
ArrayList<Game> bw = BedwarsRel.getInstance().getGameManager().getGames();
|
||||
for (Game game : bw) {
|
||||
if (game.getState().equals(GameState.RUNNING)) {
|
||||
ShopReplacer.replaceShop(game.getName(), sender);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/main/java/ldcr/BedwarsXP/utils/ReflectionUtils.java
Normal file
30
src/main/java/ldcr/BedwarsXP/utils/ReflectionUtils.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class ReflectionUtils {
|
||||
private ReflectionUtils() {
|
||||
}
|
||||
|
||||
public static <T, R> void setPrivateValue(T r, String f, R value) throws ReflectiveOperationException {
|
||||
Class<?> clazz = r.getClass();
|
||||
Field field = clazz.getDeclaredField(f);
|
||||
field.setAccessible(true);
|
||||
field.set(r, value);
|
||||
field.setAccessible(false);
|
||||
}
|
||||
|
||||
public static <T> Field getField(T r, String f) throws ReflectiveOperationException {
|
||||
Class<?> clazz = r.getClass();
|
||||
return clazz.getDeclaredField(f);
|
||||
}
|
||||
|
||||
public static boolean isClassFound(String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
19
src/main/java/ldcr/BedwarsXP/utils/ResourceUtils.java
Normal file
19
src/main/java/ldcr/BedwarsXP/utils/ResourceUtils.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import ldcr.BedwarsXP.Config;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ResourceUtils {
|
||||
public static Integer convertResToXP(ItemStack stack) {
|
||||
if (stack == null)
|
||||
return null;
|
||||
if (Config.resources.containsKey(stack.getType()))
|
||||
return Config.resources.get(stack.getType()) * stack.getAmount();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int convertResToXPExact(ItemStack item) {
|
||||
Integer result = convertResToXP(item);
|
||||
return result == null ? 0 : result;
|
||||
}
|
||||
}
|
||||
9
src/main/java/ldcr/BedwarsXP/utils/SendMessageUtils.java
Normal file
9
src/main/java/ldcr/BedwarsXP/utils/SendMessageUtils.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
public class SendMessageUtils {
|
||||
public static void sendMessage(CommandSender sender, String... message) {
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
21
src/main/java/ldcr/BedwarsXP/utils/SoundMachine.java
Normal file
21
src/main/java/ldcr/BedwarsXP/utils/SoundMachine.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import org.bukkit.Sound;
|
||||
|
||||
public class SoundMachine {
|
||||
public static Sound get(String v18, String v19) {
|
||||
try {
|
||||
// Try get old sound name
|
||||
return Sound.valueOf(v18);
|
||||
} catch (IllegalArgumentException e1) {
|
||||
try {
|
||||
// Try get new sound name
|
||||
return Sound.valueOf(v19);
|
||||
} catch (IllegalArgumentException e2) {
|
||||
// not found
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
17
src/main/java/ldcr/BedwarsXP/utils/YamlUtils.java
Normal file
17
src/main/java/ldcr/BedwarsXP/utils/YamlUtils.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package ldcr.BedwarsXP.utils;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
public class YamlUtils {
|
||||
public static YamlConfiguration loadYamlUTF8(File file) throws IOException {
|
||||
String yaml = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
|
||||
StringReader sr = new StringReader(yaml);
|
||||
return YamlConfiguration.loadConfiguration(sr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package sakura.kooi.utils.GithubUpdateChecker;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Cleanup;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class UpdateChecker {
|
||||
private String user;
|
||||
private String repo;
|
||||
private String currentVersion;
|
||||
private Consumer<String> callback;
|
||||
|
||||
public void check() throws IOException {
|
||||
URL url = new URL("https://api.github.com/repos/" + user + "/" + repo + "/releases/latest");
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
@Cleanup BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
String line;
|
||||
StringBuilder result = new StringBuilder();
|
||||
while ((line = rd.readLine()) != null) {
|
||||
result.append(line);
|
||||
}
|
||||
JsonParser parser = new JsonParser();
|
||||
|
||||
JsonObject json = parser.parse(result.toString()).getAsJsonObject();
|
||||
if (json.has("tag_name") && json.has("html_url")) {
|
||||
String tag = json.get("tag_name").getAsString();
|
||||
String link = json.get("html_url").getAsString();
|
||||
|
||||
if (currentVersion.compareTo(tag) < 0) {
|
||||
callback.accept(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
62
src/main/resources/config.yml
Normal file
62
src/main/resources/config.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
###############################
|
||||
# BedwarsXP 经验起床插件 #
|
||||
# By.SakuraKooi #
|
||||
###############################
|
||||
|
||||
# 关闭更新检查
|
||||
Disable_UpdateChecker: false
|
||||
|
||||
#设置资源可兑换为的XP数
|
||||
XP:
|
||||
# 铜可兑换为的XP
|
||||
bronze: 1
|
||||
# 铁可兑换为的XP
|
||||
iron: 5
|
||||
# 金可兑换为的XP
|
||||
gold: 10
|
||||
# 如有其他自行添加的资源也可以在此处按格式添加
|
||||
#custom: 233
|
||||
# 请务必保证起床插件中配置的资源在此处都有对应经验值
|
||||
|
||||
#获得XP的提示
|
||||
# 使用%xp%代替获得的XP
|
||||
# 插件会尝试使用ActionBar来发送,如发送失败(版本不匹配等原因)会使用聊天发送
|
||||
# 更改为空('')来禁用发送信息
|
||||
Message: '&a你获得了 &6&l%xp% &a点经验'
|
||||
|
||||
#是否在商店新增将经验重新兑换回铜铁金的菜单
|
||||
Add_Res_Shop: true
|
||||
|
||||
#玩家死亡扣除经验
|
||||
# 扣除的经验 = 玩家拥有经验 x (DeathCostXP)%
|
||||
# 请填写0-100 (百分比)
|
||||
# 设置为0关闭此功能
|
||||
# 固定扣除功能已被移除
|
||||
DeathCostXP: 0
|
||||
|
||||
#玩家死亡掉落经验
|
||||
# 开启此项后玩家死亡扣除的经验将掉在地上, 可以被其他玩家捡起
|
||||
# 掉落的经验 = 玩家拥有经验 x (DeathCostXP)% x (DeathDropXP)%
|
||||
# 请填写0-100 (百分比)
|
||||
# 设置为0关闭此功能
|
||||
DeathDropXP: 100
|
||||
|
||||
#死亡直接把经验添加给击杀者而不是掉落经验瓶
|
||||
DontDropExpBottle: false
|
||||
|
||||
#玩家可携带的最大经验
|
||||
# 超过该经验将无法捡取
|
||||
# 设置为0关闭此功能
|
||||
MaxXP: 0
|
||||
MaxXPMessage: '&4你携带的经验已达上限'
|
||||
|
||||
#完全经验起床模式
|
||||
# 设置为false : 玩家捡取资源获得经验,在商店将经验重新兑换回铜铁金购买东西
|
||||
# 设置为true : 玩家捡取资源获得经验,并可以在商店直接使用经验购买东西
|
||||
Full_XP_Bedwars: true
|
||||
|
||||
#配置文件版本
|
||||
# 请务必不要动这个
|
||||
# 乱动此项导致配置文件被重置概不负责→_→
|
||||
ConfigVersion: 2
|
||||
|
||||
1
src/main/resources/enabledGames.yml
Normal file
1
src/main/resources/enabledGames.yml
Normal file
@@ -0,0 +1 @@
|
||||
enabledGame:
|
||||
81
src/main/resources/language-en.yml
Normal file
81
src/main/resources/language-en.yml
Normal file
@@ -0,0 +1,81 @@
|
||||
# Wanna English? Just overwrites language.yml with this file :)
|
||||
|
||||
# You should replace single quote(') with two single quote('')
|
||||
# eg: player's -> player''s
|
||||
|
||||
# Loading configuration
|
||||
LOADING_CONFIGURATION: 'Loading configuration...'
|
||||
CONFIGURATION_FILE_NOT_EXISTS: 'Configuration file not exists, create it...'
|
||||
OLD_VERSION_CONFIGURATION: 'Your configuration is outdated and cannot be load!'
|
||||
OLD_CONFIGURATION_BACKUPED: 'Your configuration has been renamed to [config.bak.yml], creating new one...'
|
||||
NEW_CONFIGURATION_SAVED: 'New configuration is created, continue...'
|
||||
|
||||
RESOURCE_SHOP_ENABLED: 'Enabled XP-Resource shop'
|
||||
DEATH_COST_XP_PERCENT: 'Death will take %percent%% XP'
|
||||
DEATH_DROP_XP_DISABLED: 'Disabled Death-drop-XP'
|
||||
DEATH_DROP_XP_PERCEMT: 'Death will drop %percent%% XP'
|
||||
DEATH_DROP_EXP_BOTTLE_DISABLED: 'Disabled Death-drop-ExpBottle (Directly add to killer instead)'
|
||||
MAX_XP_LIMIT_DISABLED: 'Disabled Max-XP-limit'
|
||||
MAX_XP_LIMIT_ENABLED: 'Max XP limit is %value%'
|
||||
ALL_TRADES_USE_XP_ENABLED: 'Enabled All-trade-use-XP'
|
||||
|
||||
LOADING_RESOURCES_VALUE: 'Loading resource data...'
|
||||
FOUNDED_RESOURCE: 'Resource %resource% (%material%) = %value%XP'
|
||||
|
||||
WARN_YOU_NEEDS_ENABLE_BEDWARSXP_MANUALLY: 'You need to use [/bwxp enable] to enable XP mode for a game!'
|
||||
|
||||
# Enabling plugin
|
||||
FINDING_BEDWARSREL: 'Finding BedwarsRel...'
|
||||
BEDWARSREL_NOT_SUPPORTED: 'Sorry, Your BedwarsRel is not supported!'
|
||||
PLEASE_UPDATE_BEDWARSREL: 'Please update your BedwarsRel.'
|
||||
BEDWARSREL_SUPPORTED: 'Supported BedwarsRel found!'
|
||||
BEDWARSREL_NOT_FOUND: 'BedwarsRel not found!'
|
||||
|
||||
ERROR_OCCURED_WHILE_LOADING: 'An error occurred while loading BedwarsXP'
|
||||
REPORT_ISSUE_HERE: 'Report it at here'
|
||||
|
||||
SUCCESSFULLY_LOADED: 'BedwarsXP has been successfully loaded!'
|
||||
REPORT_ISSUE_AND_SUGGESTION_HERE: 'BUG Report | Suggestions'
|
||||
|
||||
# Commands
|
||||
YOU_DONT_HAVE_PERMISSION_TO_EXECUTE_THIS_COMMAND: 'You dont have permission to execute this command'
|
||||
UNEXCEPTED_EXCEPTION_CAUGHT: 'An unexpected error caught while executing the command.'
|
||||
ERROR_OCCURED: 'Sorry, An error occurred.'
|
||||
|
||||
# Main command
|
||||
HELP_MAIN_RELOAD: '/bwxp reload Reload BedwarsXP'
|
||||
HELP_MAIN_ENABLE: '/bwxp enable <map> Enable XP mode'
|
||||
HELP_MAIN_DISABLE: '/bwxp disable <map> Disable XP mode'
|
||||
|
||||
SUCCESSFULLY_RELOADED: 'BedwarsXP reloaded~'
|
||||
RELOAD_GAME_RUNNING: 'Some map is running!'
|
||||
UPDATE_RUNNING_GAME: 'Updating running games...'
|
||||
|
||||
ERROR_GAME_NOT_FOUND: 'Sorry, Map %game% cannot be found'
|
||||
GAME_XP_ENABLED: 'Enabled XP mode for map %game% !'
|
||||
GAME_XP_DISABLED: 'Disabled XP mode for map %game% !'
|
||||
GAME_IS_RUNNING_RESTART_REQUIRED: 'Map %game% is running, please restart it manually!'
|
||||
|
||||
# Edit XP command
|
||||
HELP_EDITXP: '/editxp <set/add/take> <player> <xp> Modify a player''s XP'
|
||||
EDITXP_PLAYER_NOT_IN_GAME: 'Player %player% is not in game!'
|
||||
EDITXP_GAME_IS_NOT_XP_MODE: 'The map that %player% playing is not in XP mode!'
|
||||
EDITXP_XP_IS_NOT_A_NUMBER: 'The XP you typed is not a valid number!'
|
||||
EDITXP_XP_HAS_BEEN_SET_TO: 'Player %player%''s XP has been set to %xp%'
|
||||
|
||||
# Shop replacer
|
||||
ERROR_OCCURED_REPLACE_SHOP: 'Failed to replace shop for map %game%'
|
||||
SUCCESSFULLY_REPLACED_SHOP: 'Successfully replaced shop for map %game%!'
|
||||
ERROR_OCCURED_WHILE_INITALIZING_XP_SHOP: 'An error occurred while initializing XP shop for map %game%'
|
||||
|
||||
SHOP_XP_EXCHANGE_TITLE: '§6§lXP Shop'
|
||||
SHOP_XP_EXCHANGE_LORE: '§aBuy resource with XP'
|
||||
|
||||
SHOP_TRADE_XP: '§a%xp% XP'
|
||||
|
||||
# Update checker
|
||||
HAS_UPDATE: 'Your BedwarsXP is outdated! Update now -> %link%'
|
||||
|
||||
# Others
|
||||
ERROR_UNSUPPORTED_VERSION_ACTIONBAR_MAY_NOT_WORK: 'Unsupported server version, ActionBar may not works'
|
||||
ERROR_OCCURRED_WHILE_LOADING: 'An unexpected error occurred while loading plugin'
|
||||
77
src/main/resources/language.yml
Normal file
77
src/main/resources/language.yml
Normal file
@@ -0,0 +1,77 @@
|
||||
# Loading configuration
|
||||
|
||||
LOADING_CONFIGURATION: '正在加载配置文件...'
|
||||
CONFIGURATION_FILE_NOT_EXISTS: '配置文件不存在, 正在创建...'
|
||||
OLD_VERSION_CONFIGURATION: '您的配置文件版本过老无法加载'
|
||||
OLD_CONFIGURATION_BACKUPED: '已备份您的配置文件为 [config.bak.yml] ,开始初始化新版本配置文件'
|
||||
NEW_CONFIGURATION_SAVED: '配置文件初始化完成, 继续加载配置...'
|
||||
|
||||
RESOURCE_SHOP_ENABLED: '已启用经验兑换资源商店'
|
||||
DEATH_COST_XP_PERCENT: '死亡扣除 %percent%% 经验'
|
||||
DEATH_DROP_XP_DISABLED: '死亡掉落经验已关闭'
|
||||
DEATH_DROP_XP_PERCEMT: '死亡掉落经验占扣除经验 %percent%%'
|
||||
DEATH_DROP_EXP_BOTTLE_DISABLED: '死亡掉落经验瓶已关闭 (直接添加给击杀者)'
|
||||
MAX_XP_LIMIT_DISABLED: '最大经验限制已关闭'
|
||||
MAX_XP_LIMIT_ENABLED: '最大经验限制设置为 %value%'
|
||||
ALL_TRADES_USE_XP_ENABLED: '完全经验起床模式已启动'
|
||||
|
||||
LOADING_RESOURCES_VALUE: '开始加载资源价值数据'
|
||||
FOUNDED_RESOURCE: '发现资源 %resource% 物品:%material% 价值 %value%'
|
||||
|
||||
WARN_YOU_NEEDS_ENABLE_BEDWARSXP_MANUALLY: '注意,在新版本中你需要手动使用/bwxp enable来启用游戏的经验起床模式'
|
||||
|
||||
# Enabling plugin
|
||||
FINDING_BEDWARSREL: '正在寻找BedwarsRel插件...'
|
||||
BEDWARSREL_NOT_SUPPORTED: '抱歉, BedwarsXP不再支持旧版BedwarsRel!'
|
||||
PLEASE_UPDATE_BEDWARSREL: '请更新你的BedwarsRel至1.3.6以上版本.'
|
||||
BEDWARSREL_SUPPORTED: '已发现受支持的BedwarsRel插件!'
|
||||
BEDWARSREL_NOT_FOUND: '没有找到支持的BedwarsRel! 你可能没有安装或使用了不受支持的版本!'
|
||||
|
||||
ERROR_OCCURED_WHILE_LOADING: 'BedwarsXP加载出错'
|
||||
REPORT_ISSUE_HERE: '请前往此处反馈'
|
||||
|
||||
SUCCESSFULLY_LOADED: '成功加载BedwarsXP经验起床插件'
|
||||
REPORT_ISSUE_AND_SUGGESTION_HERE: 'BUG反馈 | 提交建议'
|
||||
|
||||
# Commands
|
||||
YOU_DONT_HAVE_PERMISSION_TO_EXECUTE_THIS_COMMAND: '你没有权限执行此命令'
|
||||
UNEXCEPTED_EXCEPTION_CAUGHT: '在执行您的命令时出现了异常错误'
|
||||
ERROR_OCCURED: '错误: 在执行您的操作时发生了错误'
|
||||
|
||||
# Main command
|
||||
HELP_MAIN_RELOAD: '/bwxp reload 重载插件配置'
|
||||
HELP_MAIN_ENABLE: '/bwxp enable <游戏> 激活指定游戏的经验起床模式'
|
||||
HELP_MAIN_DISABLE: '/bwxp disable <游戏> 禁用指定游戏的经验起床模式'
|
||||
|
||||
SUCCESSFULLY_RELOADED: '成功重载配置文件~'
|
||||
RELOAD_GAME_RUNNING: '当前有游戏正在运行'
|
||||
UPDATE_RUNNING_GAME: '开始更新运行中的游戏的经验商店'
|
||||
|
||||
ERROR_GAME_NOT_FOUND: '错误: 找不到游戏 %game%'
|
||||
GAME_XP_ENABLED: '成功激活了游戏 %game% 的经验起床模式'
|
||||
GAME_XP_DISABLED: '成功禁用了游戏 %game% 的经验起床模式'
|
||||
GAME_IS_RUNNING_RESTART_REQUIRED: '游戏 %game% 正在运行,请手动重启游戏'
|
||||
|
||||
# Edit XP command
|
||||
HELP_EDITXP: '/editxp <set/add/take> <玩家> <经验值> 设置其他玩家的经验值'
|
||||
EDITXP_PLAYER_NOT_IN_GAME: '玩家 %player% 不在游戏中!'
|
||||
EDITXP_GAME_IS_NOT_XP_MODE: '玩家 %player% 所在的游戏没有开启经验起床模式!'
|
||||
EDITXP_XP_IS_NOT_A_NUMBER: '输入经验值的不是一个有效数字!'
|
||||
EDITXP_XP_HAS_BEEN_SET_TO: '玩家 %player% 的经验值已被设置为 %xp%'
|
||||
|
||||
# Shop replacer
|
||||
ERROR_OCCURED_REPLACE_SHOP: '为地图 %game% 替换原始商店为经验商店失败'
|
||||
SUCCESSFULLY_REPLACED_SHOP: '为地图 %game% 替换经验商店成功!'
|
||||
ERROR_OCCURED_WHILE_INITALIZING_XP_SHOP: '为地图 %game% 初始化经验商店时出错'
|
||||
|
||||
SHOP_XP_EXCHANGE_TITLE: '§6§l经验兑换资源'
|
||||
SHOP_XP_EXCHANGE_LORE: '§a将你的经验兑换成物品'
|
||||
|
||||
SHOP_TRADE_XP: '§a%xp% 经验'
|
||||
|
||||
# Update checker
|
||||
HAS_UPDATE: 'BedwarsXP 发布了新版本! 下载 -> %link%'
|
||||
|
||||
# Others
|
||||
ERROR_UNSUPPORTED_VERSION_ACTIONBAR_MAY_NOT_WORK: '解析服务端版本失败, ActionBar提示可能出错'
|
||||
ERROR_OCCURRED_WHILE_LOADING: '加载插件时发生了异常错误'
|
||||
18
src/main/resources/plugin.yml
Normal file
18
src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
name: BedwarsXP
|
||||
main: ldcr.BedwarsXP.BedwarsXP
|
||||
version: 2.1.3
|
||||
author: SakuraKooi
|
||||
depend: [BedwarsRel]
|
||||
commands:
|
||||
bedwarsxp:
|
||||
description: 经验起床
|
||||
usage: /bedwarsxp
|
||||
aliases: [bwxp]
|
||||
bedwarsxpedit:
|
||||
description: 修改玩家经验值
|
||||
usage: /bedwarsxpedit
|
||||
aliases: [editxp]
|
||||
permissions:
|
||||
bedwarsxp.admin:
|
||||
description: 经验起床相关管理权限.
|
||||
default: op
|
||||
Reference in New Issue
Block a user