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