Compare commits
19 Commits
c1f8a31bd3
...
74eda38558
Author | SHA1 | Date |
---|---|---|
Fisher | 74eda38558 | |
Andreas Troelsen | 29c5d7f56d | |
Andreas Troelsen | e40fc6ef84 | |
Andreas Troelsen | be6fd85a6d | |
Andreas Troelsen | b881943656 | |
Andreas Troelsen | 8e5d2f0d23 | |
Andreas Troelsen | 3b7b638b00 | |
Andreas Troelsen | eb51a31720 | |
Andreas Troelsen | 82f00c5535 | |
Andreas Troelsen | d8fdbb80c0 | |
Andreas Troelsen | e5ffe169a1 | |
Andreas Troelsen | 798ae0f578 | |
Andreas Troelsen | 84776990b9 | |
Andreas Troelsen | 590f877756 | |
Andreas Troelsen | 932b9de8f2 | |
Andreas Troelsen | 614d95683e | |
Andreas Troelsen | 4c855e6705 | |
Fisher2911 | 3d107479b5 | |
Fisher2911 | d8304ce0b6 |
|
@ -1,15 +1,20 @@
|
||||||
name: build
|
name: build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout source code'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 'Set up JDK'
|
- name: 'Set up JDK'
|
||||||
|
@ -19,11 +24,56 @@ jobs:
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
cache: 'gradle'
|
cache: 'gradle'
|
||||||
|
|
||||||
- name: 'Build, test, and package'
|
- name: 'Build'
|
||||||
run: ./gradlew build --no-daemon
|
run: ./gradlew build --no-daemon
|
||||||
|
|
||||||
- name: 'Upload artifact'
|
- name: 'Upload artifact'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: MobArena.jar
|
name: MobArena.jar
|
||||||
path: build/libs/MobArena.jar
|
path: build/libs/MobArena-*.jar
|
||||||
|
|
||||||
|
- name: 'Output version'
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
version=$(
|
||||||
|
unzip -p build/libs/MobArena-*.jar plugin.yml \
|
||||||
|
| grep '^version: ' \
|
||||||
|
| awk '{printf $2}' \
|
||||||
|
| tr -d "'" \
|
||||||
|
)
|
||||||
|
echo "version=${version}" >> "${GITHUB_OUTPUT}"
|
||||||
|
|
||||||
|
draft:
|
||||||
|
needs: build
|
||||||
|
|
||||||
|
if: |
|
||||||
|
needs.build.result == 'success' &&
|
||||||
|
github.ref_name == 'master' &&
|
||||||
|
startsWith(github.event.head_commit.message, 'Release ') &&
|
||||||
|
!endsWith(needs.build.outputs.version, '-SNAPSHOT')
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.build.outputs.version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 'Checkout'
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 'Download artifact'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: MobArena.jar
|
||||||
|
|
||||||
|
- name: 'Extract release notes'
|
||||||
|
run: scripts/extract-release-notes -f github "${VERSION}" > release-notes.md
|
||||||
|
|
||||||
|
- name: 'Create release draft'
|
||||||
|
run: gh release create "${VERSION}" --draft --notes-file release-notes.md MobArena-*.jar
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
name: publish-curseforge
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- 'released'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag_name:
|
||||||
|
description: 'The tag name of the release to publish'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
TAG_NAME: ${{ github.event.release.tag_name || inputs.tag_name }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download release assets
|
||||||
|
run: gh release download "${TAG_NAME}"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Publish to CurseForge
|
||||||
|
run: |
|
||||||
|
echo 'Extract release notes'
|
||||||
|
changelog=$(scripts/extract-release-notes -f curse "${TAG_NAME}")
|
||||||
|
|
||||||
|
echo 'Look up game version IDs'
|
||||||
|
game_version_type_id=1
|
||||||
|
game_version_names='"1.20","1.19","1.18","1.17","1.16","1.15","1.14","1.13"'
|
||||||
|
|
||||||
|
type_condition="(.gameVersionTypeID == ${game_version_type_id})"
|
||||||
|
name_condition="(.name | startswith(${game_version_names}))"
|
||||||
|
|
||||||
|
game_version_ids=$(
|
||||||
|
curl -s -X GET 'https://minecraft.curseforge.com/api/game/versions' \
|
||||||
|
-H "X-Api-Token: ${{ secrets.CURSEFORGE_TOKEN }}" \
|
||||||
|
| jq -c ".[] | select(${type_condition} and ${name_condition}) | .id" \
|
||||||
|
| paste -sd, - \
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 'Create metadata file'
|
||||||
|
cat << EOF > metadata.jq
|
||||||
|
{
|
||||||
|
changelog: \$changelog,
|
||||||
|
changelogType: "html",
|
||||||
|
displayName: \$displayName,
|
||||||
|
gameVersions: \$gameVersions,
|
||||||
|
releaseType: "beta"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
jq -c -n \
|
||||||
|
--arg changelog "${changelog}" \
|
||||||
|
--arg displayName "MobArena v${TAG_NAME}" \
|
||||||
|
--argjson gameVersions "[${game_version_ids}]" \
|
||||||
|
-f metadata.jq \
|
||||||
|
> metadata.json
|
||||||
|
|
||||||
|
echo 'Publish build to CurseForge'
|
||||||
|
base_url='https://minecraft.curseforge.com'
|
||||||
|
project_id=31265
|
||||||
|
|
||||||
|
curl -s -X POST "${base_url}/api/projects/${project_id}/upload-file" \
|
||||||
|
-H "X-Api-Token: ${{ secrets.CURSEFORGE_TOKEN }}" \
|
||||||
|
-F 'metadata=<metadata.json' \
|
||||||
|
-F "file=@MobArena-${TAG_NAME}.jar"
|
|
@ -0,0 +1,79 @@
|
||||||
|
name: publish-hangar
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- 'released'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag_name:
|
||||||
|
description: 'The tag name of the release to publish'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
TAG_NAME: ${{ github.event.release.tag_name || inputs.tag_name }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Download release assets
|
||||||
|
run: gh release download "${TAG_NAME}"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Publish to Hangar
|
||||||
|
run: |
|
||||||
|
echo 'Extract release notes'
|
||||||
|
changelog=$(scripts/extract-release-notes -f hangar "${TAG_NAME}")
|
||||||
|
|
||||||
|
echo 'Create version upload file'
|
||||||
|
cat << EOF > version-upload.jq
|
||||||
|
{
|
||||||
|
version: \$version,
|
||||||
|
channel: "Release",
|
||||||
|
description: \$changelog,
|
||||||
|
platformDependencies: {
|
||||||
|
"PAPER": [
|
||||||
|
"1.13.x",
|
||||||
|
"1.14.x",
|
||||||
|
"1.15.x",
|
||||||
|
"1.16.x",
|
||||||
|
"1.17.x",
|
||||||
|
"1.18.x",
|
||||||
|
"1.19.x",
|
||||||
|
"1.20.x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
pluginDependencies: {},
|
||||||
|
files: [
|
||||||
|
{ platforms: ["PAPER"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
jq -c -n \
|
||||||
|
--arg version "${TAG_NAME}" \
|
||||||
|
--arg changelog "${changelog}" \
|
||||||
|
-f version-upload.jq \
|
||||||
|
> version-upload.json
|
||||||
|
|
||||||
|
echo 'Authenticate with Hangar'
|
||||||
|
base_url='https://hangar.papermc.io/api/v1'
|
||||||
|
key=${{ secrets.HANGAR_TOKEN }}
|
||||||
|
jwt=$(curl -s -X POST "${base_url}/authenticate?apiKey=${key}" | jq -r '.token')
|
||||||
|
|
||||||
|
echo 'Publish build to Hangar'
|
||||||
|
project_slug='MobArena'
|
||||||
|
curl -s -X POST "${base_url}/projects/${project_slug}/upload" \
|
||||||
|
-H "Authorization: ${jwt}" \
|
||||||
|
-F 'versionUpload=<version-upload.json;type=application/json' \
|
||||||
|
-F "files=@MobArena-${TAG_NAME}.jar"
|
|
@ -4,7 +4,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "com.garbagemule"
|
group = "com.garbagemule"
|
||||||
version = "0.107.1-SNAPSHOT"
|
version = "0.108"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
|
@ -58,7 +58,6 @@ tasks {
|
||||||
|
|
||||||
archiveBaseName = "MobArena"
|
archiveBaseName = "MobArena"
|
||||||
archiveClassifier = ""
|
archiveClassifier = ""
|
||||||
archiveVersion = ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're using shadowJar, so we can skip the regular jar task.
|
// We're using shadowJar, so we can skip the regular jar task.
|
||||||
|
|
|
@ -11,6 +11,8 @@ These changes will (most likely) be included in the next version.
|
||||||
|
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.108] - 2024-01-01
|
||||||
### Added
|
### Added
|
||||||
- Support for chest references in item syntax. The new `inv` syntax allows for referencing container indices in the config-file. This should help bridge the gap between class chests and various other parts of the config-file, such as rewards and upgrade waves.
|
- Support for chest references in item syntax. The new `inv` syntax allows for referencing container indices in the config-file. This should help bridge the gap between class chests and various other parts of the config-file, such as rewards and upgrade waves.
|
||||||
- Support for saved items. The new `/ma save-item` command can be used to save the currently held item to disk, which allows it to be used in various places in the config-file. This should help bridge the gap between the config-file and class chests for config-file centric setups.
|
- Support for saved items. The new `/ma save-item` command can be used to save the currently held item to disk, which allows it to be used in various places in the config-file. This should help bridge the gap between the config-file and class chests for config-file centric setups.
|
||||||
|
@ -259,7 +261,8 @@ Thanks to:
|
||||||
- Swatacular for help with testing bug fixes
|
- Swatacular for help with testing bug fixes
|
||||||
- Haileykins for contributions to the code base
|
- Haileykins for contributions to the code base
|
||||||
|
|
||||||
[Unreleased]: https://github.com/garbagemule/MobArena/compare/0.107...HEAD
|
[Unreleased]: https://github.com/garbagemule/MobArena/compare/0.108...HEAD
|
||||||
|
[0.108]: https://github.com/garbagemule/MobArena/compare/0.107...0.108
|
||||||
[0.107]: https://github.com/garbagemule/MobArena/compare/0.106...0.107
|
[0.107]: https://github.com/garbagemule/MobArena/compare/0.106...0.107
|
||||||
[0.106]: https://github.com/garbagemule/MobArena/compare/0.105...0.106
|
[0.106]: https://github.com/garbagemule/MobArena/compare/0.105...0.106
|
||||||
[0.105]: https://github.com/garbagemule/MobArena/compare/0.104.2...0.105
|
[0.105]: https://github.com/garbagemule/MobArena/compare/0.104.2...0.105
|
||||||
|
|
|
@ -0,0 +1,235 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
VERSION_PREFIX = '## '
|
||||||
|
SECTION_PREFIX = '### '
|
||||||
|
LIST_ITEM_PREFIX = '- '
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
lines = extract(args.version)
|
||||||
|
output(lines, args.format)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'version',
|
||||||
|
help='the version to extract release notes from the changelog for',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--format',
|
||||||
|
'-f',
|
||||||
|
choices=['github', 'hangar', 'spigot', 'curse'],
|
||||||
|
help='the format to output the release notes in',
|
||||||
|
)
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def extract(target):
|
||||||
|
filename = 'changelog.md'
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
filename = os.path.join('..', filename)
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
print('error: changelog.md not found!')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
with open(filename) as changelog:
|
||||||
|
found = False
|
||||||
|
|
||||||
|
for entry in changelog:
|
||||||
|
if entry.startswith(VERSION_PREFIX):
|
||||||
|
if found:
|
||||||
|
break
|
||||||
|
|
||||||
|
i = entry.find('[') + 1
|
||||||
|
j = entry.find(']')
|
||||||
|
version = entry[i:j]
|
||||||
|
|
||||||
|
if version == target:
|
||||||
|
if version[0].isdigit():
|
||||||
|
version = f'v{version}'
|
||||||
|
|
||||||
|
lines.append(f'{VERSION_PREFIX}{version}')
|
||||||
|
lines.append('')
|
||||||
|
found = True
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
continue
|
||||||
|
|
||||||
|
lines.append(entry.strip())
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
print(f'error: version {target} not found!')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def output(lines, fmt):
|
||||||
|
if fmt == 'github':
|
||||||
|
output_as_github_markdown(lines)
|
||||||
|
elif fmt == 'hangar':
|
||||||
|
output_as_hangar_markdown(lines)
|
||||||
|
elif fmt == 'spigot':
|
||||||
|
output_as_spigot_bbcode(lines)
|
||||||
|
elif fmt == 'curse':
|
||||||
|
output_as_curseforge_html(lines)
|
||||||
|
else:
|
||||||
|
output_raw(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def output_as_github_markdown(lines):
|
||||||
|
"""
|
||||||
|
GitHub Releases Markdown is printed as the raw output from the changelog
|
||||||
|
except for the version header (the first line), because the version number
|
||||||
|
is already used as the release title, so we don't want it to appear twice.
|
||||||
|
"""
|
||||||
|
output_raw(lines[1:])
|
||||||
|
|
||||||
|
|
||||||
|
def output_as_hangar_markdown(lines):
|
||||||
|
"""
|
||||||
|
Hangar Versions use Markdown in the same format as GitHub Releases, so we
|
||||||
|
don't actually need to do anything else here either. Just strip the first
|
||||||
|
line so we don't get a duplicate header.
|
||||||
|
"""
|
||||||
|
output_raw(lines[1:])
|
||||||
|
|
||||||
|
|
||||||
|
def output_as_spigot_bbcode(lines):
|
||||||
|
"""
|
||||||
|
Spigot uses BBCode for resource update descriptions. It's very similar to
|
||||||
|
regular HTML, which makes it fairly easy to convert from Markdown. We just
|
||||||
|
need to use a [FONT] tag with Courier New for code bits.
|
||||||
|
"""
|
||||||
|
listing = False
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if line.startswith(VERSION_PREFIX):
|
||||||
|
i = len(VERSION_PREFIX)
|
||||||
|
version = line[i:]
|
||||||
|
print(f'[B]{version}[/B]')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(SECTION_PREFIX):
|
||||||
|
if listing:
|
||||||
|
print('[/LIST]')
|
||||||
|
listing = False
|
||||||
|
|
||||||
|
i = len(SECTION_PREFIX)
|
||||||
|
section = line[i:]
|
||||||
|
print(f'[B]{section}:[/B]')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(LIST_ITEM_PREFIX):
|
||||||
|
if not listing:
|
||||||
|
print('[LIST]')
|
||||||
|
listing = True
|
||||||
|
|
||||||
|
i = len(LIST_ITEM_PREFIX)
|
||||||
|
item = line[i:]
|
||||||
|
|
||||||
|
# Replace **bold** text
|
||||||
|
item = re.sub(r'\*\*(.*?)\*\*', r'[B]\1[/B]', item)
|
||||||
|
|
||||||
|
# Replace _italic_ text
|
||||||
|
item = re.sub(r'_(.*?)_', r'[I]\1[/I]', item)
|
||||||
|
|
||||||
|
# Replace `code` text
|
||||||
|
item = re.sub(r'`(.*?)`', r'[FONT=Courier New]\1[/FONT]', item)
|
||||||
|
|
||||||
|
# Replace [links](url)
|
||||||
|
item = re.sub(r'\[([^\]]+)]\(([^)]+)\)', r'[URL=\2]\1[/URL]', item)
|
||||||
|
|
||||||
|
print(f'[*]{item}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(line) > 0:
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
if listing:
|
||||||
|
print('[/LIST]')
|
||||||
|
|
||||||
|
|
||||||
|
def output_as_curseforge_html(lines):
|
||||||
|
"""
|
||||||
|
CurseForge uses regular HTML for file update descriptions, which makes it
|
||||||
|
fairly easy to convert from Markdown. Angled brackets need to be replaced
|
||||||
|
with their HTML entity equivalents, but other than that it's very similar
|
||||||
|
to the Spigot BBCode conversion.
|
||||||
|
"""
|
||||||
|
listing = False
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if line.startswith(VERSION_PREFIX):
|
||||||
|
i = len(VERSION_PREFIX)
|
||||||
|
version = line[i:]
|
||||||
|
print(f'<p><strong>{version}</strong></p>')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(SECTION_PREFIX):
|
||||||
|
if listing:
|
||||||
|
print('</ul>')
|
||||||
|
listing = False
|
||||||
|
|
||||||
|
i = len(SECTION_PREFIX)
|
||||||
|
section = line[i:]
|
||||||
|
print(f'<p><strong>{section}:</strong></p>')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.startswith(LIST_ITEM_PREFIX):
|
||||||
|
if not listing:
|
||||||
|
print('<ul>')
|
||||||
|
listing = True
|
||||||
|
|
||||||
|
i = len(LIST_ITEM_PREFIX)
|
||||||
|
item = line[i:]
|
||||||
|
|
||||||
|
# Replace angled brackets
|
||||||
|
item = item.replace('<', '<')
|
||||||
|
item = item.replace('>', '>')
|
||||||
|
|
||||||
|
# Replace **bold** text
|
||||||
|
item = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', item)
|
||||||
|
|
||||||
|
# Replace _italic_ text
|
||||||
|
item = re.sub(r'_(.*?)_', r'<emph>\1</emph>', item)
|
||||||
|
|
||||||
|
# Replace `code` text
|
||||||
|
item = re.sub(r'`(.*?)`', r'<code>\1</code>', item)
|
||||||
|
|
||||||
|
# Replace [links](url)
|
||||||
|
item = re.sub(r'\[([^\]]+)]\(([^)]+)\)', r'<a href="\2">\1</a>', item)
|
||||||
|
|
||||||
|
print(f'<li>{item}</li>')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(line) > 0:
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
if listing:
|
||||||
|
print('</ul>')
|
||||||
|
|
||||||
|
|
||||||
|
def output_raw(lines):
|
||||||
|
[print(line.strip()) for line in lines]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -268,6 +268,9 @@ public class ArenaClass
|
||||||
if (arena != null) {
|
if (arena != null) {
|
||||||
try {
|
try {
|
||||||
arena.getInventoryManager().equip(p);
|
arena.getInventoryManager().equip(p);
|
||||||
|
if (arena.isKeepDrops()) {
|
||||||
|
arena.getInventoryManager().setOriginalItemsPDC(arena.getPlugin(), p);
|
||||||
|
}
|
||||||
removeBannedItems(p.getInventory());
|
removeBannedItems(p.getInventory());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
am.getPlugin().getLogger().severe("Failed to give " + p.getName() + " their own items: " + e.getMessage());
|
am.getPlugin().getLogger().severe("Failed to give " + p.getName() + " their own items: " + e.getMessage());
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
package com.garbagemule.MobArena;
|
package com.garbagemule.MobArena;
|
||||||
|
|
||||||
import static com.garbagemule.MobArena.util.config.ConfigUtils.makeSection;
|
|
||||||
|
|
||||||
import com.garbagemule.MobArena.ScoreboardManager.NullScoreboardManager;
|
import com.garbagemule.MobArena.ScoreboardManager.NullScoreboardManager;
|
||||||
import com.garbagemule.MobArena.announce.Announcer;
|
import com.garbagemule.MobArena.announce.Announcer;
|
||||||
import com.garbagemule.MobArena.announce.MessengerAnnouncer;
|
import com.garbagemule.MobArena.announce.MessengerAnnouncer;
|
||||||
import com.garbagemule.MobArena.announce.TitleAnnouncer;
|
import com.garbagemule.MobArena.announce.TitleAnnouncer;
|
||||||
import com.garbagemule.MobArena.steps.Step;
|
|
||||||
import com.garbagemule.MobArena.steps.StepFactory;
|
|
||||||
import com.garbagemule.MobArena.steps.PlayerJoinArena;
|
|
||||||
import com.garbagemule.MobArena.steps.PlayerSpecArena;
|
|
||||||
import com.garbagemule.MobArena.events.ArenaEndEvent;
|
import com.garbagemule.MobArena.events.ArenaEndEvent;
|
||||||
import com.garbagemule.MobArena.events.ArenaPlayerDeathEvent;
|
import com.garbagemule.MobArena.events.ArenaPlayerDeathEvent;
|
||||||
import com.garbagemule.MobArena.events.ArenaPlayerJoinEvent;
|
import com.garbagemule.MobArena.events.ArenaPlayerJoinEvent;
|
||||||
|
@ -22,6 +16,12 @@ import com.garbagemule.MobArena.region.ArenaRegion;
|
||||||
import com.garbagemule.MobArena.repairable.Repairable;
|
import com.garbagemule.MobArena.repairable.Repairable;
|
||||||
import com.garbagemule.MobArena.repairable.RepairableComparator;
|
import com.garbagemule.MobArena.repairable.RepairableComparator;
|
||||||
import com.garbagemule.MobArena.repairable.RepairableContainer;
|
import com.garbagemule.MobArena.repairable.RepairableContainer;
|
||||||
|
import com.garbagemule.MobArena.steps.CompositeStep;
|
||||||
|
import com.garbagemule.MobArena.steps.KeepDropsStep;
|
||||||
|
import com.garbagemule.MobArena.steps.PlayerJoinArena;
|
||||||
|
import com.garbagemule.MobArena.steps.PlayerSpecArena;
|
||||||
|
import com.garbagemule.MobArena.steps.Step;
|
||||||
|
import com.garbagemule.MobArena.steps.StepFactory;
|
||||||
import com.garbagemule.MobArena.things.InvalidThingInputString;
|
import com.garbagemule.MobArena.things.InvalidThingInputString;
|
||||||
import com.garbagemule.MobArena.things.Thing;
|
import com.garbagemule.MobArena.things.Thing;
|
||||||
import com.garbagemule.MobArena.things.ThingPicker;
|
import com.garbagemule.MobArena.things.ThingPicker;
|
||||||
|
@ -73,8 +73,9 @@ import java.util.concurrent.PriorityBlockingQueue;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ArenaImpl implements Arena
|
import static com.garbagemule.MobArena.util.config.ConfigUtils.makeSection;
|
||||||
{
|
|
||||||
|
public class ArenaImpl implements Arena {
|
||||||
// General stuff
|
// General stuff
|
||||||
private MobArena plugin;
|
private MobArena plugin;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -98,10 +99,10 @@ public class ArenaImpl implements Arena
|
||||||
private Leaderboard leaderboard;
|
private Leaderboard leaderboard;
|
||||||
|
|
||||||
// Player stuff
|
// Player stuff
|
||||||
private InventoryManager inventoryManager;
|
private InventoryManager inventoryManager;
|
||||||
private RewardManager rewardManager;
|
private RewardManager rewardManager;
|
||||||
private ClassLimitManager limitManager;
|
private ClassLimitManager limitManager;
|
||||||
private Map<Player,ArenaPlayer> arenaPlayerMap;
|
private Map<Player, ArenaPlayer> arenaPlayerMap;
|
||||||
|
|
||||||
private Set<Player> arenaPlayers, lobbyPlayers, readyPlayers, specPlayers, deadPlayers;
|
private Set<Player> arenaPlayers, lobbyPlayers, readyPlayers, specPlayers, deadPlayers;
|
||||||
private Set<Player> movingPlayers;
|
private Set<Player> movingPlayers;
|
||||||
|
@ -110,20 +111,20 @@ public class ArenaImpl implements Arena
|
||||||
|
|
||||||
// Classes stuff
|
// Classes stuff
|
||||||
private ArenaClass defaultClass;
|
private ArenaClass defaultClass;
|
||||||
private Map<String,ArenaClass> classes;
|
private Map<String, ArenaClass> classes;
|
||||||
|
|
||||||
// Blocks and pets
|
// Blocks and pets
|
||||||
private PriorityBlockingQueue<Repairable> repairQueue;
|
private PriorityBlockingQueue<Repairable> repairQueue;
|
||||||
private Set<Block> blocks;
|
private Set<Block> blocks;
|
||||||
private LinkedList<Repairable> repairables, containables;
|
private LinkedList<Repairable> repairables, containables;
|
||||||
|
|
||||||
// Monster stuff
|
// Monster stuff
|
||||||
private MonsterManager monsterManager;
|
private MonsterManager monsterManager;
|
||||||
|
|
||||||
// Wave stuff
|
// Wave stuff
|
||||||
private WaveManager waveManager;
|
private WaveManager waveManager;
|
||||||
private MASpawnThread spawnThread;
|
private MASpawnThread spawnThread;
|
||||||
private SheepBouncer sheepBouncer;
|
private SheepBouncer sheepBouncer;
|
||||||
private Map<Integer, ThingPicker> everyWaveMap, afterWaveMap;
|
private Map<Integer, ThingPicker> everyWaveMap, afterWaveMap;
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
|
@ -132,6 +133,7 @@ public class ArenaImpl implements Arena
|
||||||
private AutoStartTimer autoStartTimer;
|
private AutoStartTimer autoStartTimer;
|
||||||
private StartDelayTimer startDelayTimer;
|
private StartDelayTimer startDelayTimer;
|
||||||
private boolean isolatedChat;
|
private boolean isolatedChat;
|
||||||
|
private boolean keepDrops;
|
||||||
|
|
||||||
// Warp offsets
|
// Warp offsets
|
||||||
private double arenaWarpOffset;
|
private double arenaWarpOffset;
|
||||||
|
@ -156,37 +158,37 @@ public class ArenaImpl implements Arena
|
||||||
if (world == null)
|
if (world == null)
|
||||||
throw new NullPointerException("[MobArena] ERROR! World for arena '" + name + "' does not exist!");
|
throw new NullPointerException("[MobArena] ERROR! World for arena '" + name + "' does not exist!");
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.slug = Slugs.create(name);
|
this.slug = Slugs.create(name);
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.settings = makeSection(section, "settings");
|
this.settings = makeSection(section, "settings");
|
||||||
this.region = new ArenaRegion(section, this);
|
this.region = new ArenaRegion(section, this);
|
||||||
|
|
||||||
this.enabled = settings.getBoolean("enabled", false);
|
this.enabled = settings.getBoolean("enabled", false);
|
||||||
this.protect = settings.getBoolean("protect", true);
|
this.protect = settings.getBoolean("protect", true);
|
||||||
this.running = false;
|
this.running = false;
|
||||||
this.edit = false;
|
this.edit = false;
|
||||||
|
|
||||||
this.inventoryManager = new InventoryManager();
|
this.inventoryManager = new InventoryManager();
|
||||||
this.rewardManager = new RewardManager(this);
|
this.rewardManager = new RewardManager(this);
|
||||||
|
|
||||||
// Warps, points and locations
|
// Warps, points and locations
|
||||||
this.leaderboard = new Leaderboard(plugin, this, region.getLeaderboard());
|
this.leaderboard = new Leaderboard(plugin, this, region.getLeaderboard());
|
||||||
|
|
||||||
// Player stuff
|
// Player stuff
|
||||||
this.arenaPlayerMap = new HashMap<>();
|
this.arenaPlayerMap = new HashMap<>();
|
||||||
this.arenaPlayers = new HashSet<>();
|
this.arenaPlayers = new HashSet<>();
|
||||||
this.lobbyPlayers = new HashSet<>();
|
this.lobbyPlayers = new HashSet<>();
|
||||||
this.readyPlayers = new HashSet<>();
|
this.readyPlayers = new HashSet<>();
|
||||||
this.specPlayers = new HashSet<>();
|
this.specPlayers = new HashSet<>();
|
||||||
this.deadPlayers = new HashSet<>();
|
this.deadPlayers = new HashSet<>();
|
||||||
this.randoms = new HashSet<>();
|
this.randoms = new HashSet<>();
|
||||||
this.movingPlayers = new HashSet<>();
|
this.movingPlayers = new HashSet<>();
|
||||||
this.leavingPlayers = new HashSet<>();
|
this.leavingPlayers = new HashSet<>();
|
||||||
|
|
||||||
// Classes, items and permissions
|
// Classes, items and permissions
|
||||||
this.classes = plugin.getArenaMaster().getClasses();
|
this.classes = plugin.getArenaMaster().getClasses();
|
||||||
this.limitManager = new ClassLimitManager(this, classes, makeSection(section, "class-limits"));
|
this.limitManager = new ClassLimitManager(this, classes, makeSection(section, "class-limits"));
|
||||||
|
|
||||||
String defaultClassName = settings.getString("default-class", null);
|
String defaultClassName = settings.getString("default-class", null);
|
||||||
|
@ -196,23 +198,23 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blocks and pets
|
// Blocks and pets
|
||||||
this.repairQueue = new PriorityBlockingQueue<>(100, new RepairableComparator());
|
this.repairQueue = new PriorityBlockingQueue<>(100, new RepairableComparator());
|
||||||
this.blocks = new HashSet<>();
|
this.blocks = new HashSet<>();
|
||||||
this.repairables = new LinkedList<>();
|
this.repairables = new LinkedList<>();
|
||||||
this.containables = new LinkedList<>();
|
this.containables = new LinkedList<>();
|
||||||
|
|
||||||
// Monster stuff
|
// Monster stuff
|
||||||
this.monsterManager = new MonsterManager();
|
this.monsterManager = new MonsterManager();
|
||||||
|
|
||||||
// Wave stuff
|
// Wave stuff
|
||||||
this.waveManager = new WaveManager(this, section.getConfigurationSection("waves"));
|
this.waveManager = new WaveManager(this, section.getConfigurationSection("waves"));
|
||||||
this.everyWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "every");
|
this.everyWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "every");
|
||||||
this.afterWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "after");
|
this.afterWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "after");
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
this.eventListener = new ArenaListener(this, plugin);
|
this.eventListener = new ArenaListener(this, plugin);
|
||||||
this.allowMonsters = world.getAllowMonsters();
|
this.allowMonsters = world.getAllowMonsters();
|
||||||
this.allowAnimals = world.getAllowAnimals();
|
this.allowAnimals = world.getAllowAnimals();
|
||||||
|
|
||||||
this.entryFee = new ArrayList<>();
|
this.entryFee = new ArrayList<>();
|
||||||
String feeString = settings.getString("entry-fee", "");
|
String feeString = settings.getString("entry-fee", "");
|
||||||
|
@ -227,10 +229,12 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.autoStartTimer = new AutoStartTimer(this);
|
this.autoStartTimer = new AutoStartTimer(this);
|
||||||
this.startDelayTimer = new StartDelayTimer(this, autoStartTimer);
|
this.startDelayTimer = new StartDelayTimer(this, autoStartTimer);
|
||||||
|
|
||||||
this.isolatedChat = settings.getBoolean("isolated-chat", false);
|
this.isolatedChat = settings.getBoolean("isolated-chat", false);
|
||||||
|
|
||||||
|
this.keepDrops = settings.getBoolean("keep-drops", false);
|
||||||
|
|
||||||
this.arenaWarpOffset = settings.getDouble("arena-warp-offset", 0.0);
|
this.arenaWarpOffset = settings.getDouble("arena-warp-offset", 0.0);
|
||||||
|
|
||||||
|
@ -451,14 +455,10 @@ public class ArenaImpl implements Arena
|
||||||
return scoreboard;
|
return scoreboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeepDrops() {
|
||||||
|
return keepDrops;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Messenger getMessenger() {
|
public Messenger getMessenger() {
|
||||||
|
@ -652,8 +652,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void forceStart()
|
public void forceStart() {
|
||||||
{
|
|
||||||
if (running)
|
if (running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -696,8 +695,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean playerJoin(Player p, Location loc)
|
public boolean playerJoin(Player p, Location loc) {
|
||||||
{
|
|
||||||
// Fire the event and check if it's been cancelled.
|
// Fire the event and check if it's been cancelled.
|
||||||
ArenaPlayerJoinEvent event = new ArenaPlayerJoinEvent(p, this);
|
ArenaPlayerJoinEvent event = new ArenaPlayerJoinEvent(p, this);
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
plugin.getServer().getPluginManager().callEvent(event);
|
||||||
|
@ -774,8 +772,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playerReady(Player p)
|
public void playerReady(Player p) {
|
||||||
{
|
|
||||||
ArenaPlayerReadyEvent event = new ArenaPlayerReadyEvent(p, this);
|
ArenaPlayerReadyEvent event = new ArenaPlayerReadyEvent(p, this);
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
plugin.getServer().getPluginManager().callEvent(event);
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
|
@ -785,8 +782,7 @@ public class ArenaImpl implements Arena
|
||||||
readyPlayers.add(p);
|
readyPlayers.add(p);
|
||||||
|
|
||||||
int minPlayers = getMinPlayers();
|
int minPlayers = getMinPlayers();
|
||||||
if (minPlayers > 0 && lobbyPlayers.size() < minPlayers)
|
if (minPlayers > 0 && lobbyPlayers.size() < minPlayers) {
|
||||||
{
|
|
||||||
messenger.tell(p, Msg.LOBBY_NOT_ENOUGH_PLAYERS, "" + minPlayers);
|
messenger.tell(p, Msg.LOBBY_NOT_ENOUGH_PLAYERS, "" + minPlayers);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -795,8 +791,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean playerLeave(Player p)
|
public boolean playerLeave(Player p) {
|
||||||
{
|
|
||||||
// Fire the event and check if it's been cancelled.
|
// Fire the event and check if it's been cancelled.
|
||||||
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(p, this);
|
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(p, this);
|
||||||
plugin.getServer().getPluginManager().callEvent(event);
|
plugin.getServer().getPluginManager().callEvent(event);
|
||||||
|
@ -859,8 +854,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playerDeath(Player p)
|
public void playerDeath(Player p) {
|
||||||
{
|
|
||||||
// Check if we're the last player standing
|
// Check if we're the last player standing
|
||||||
boolean last = arenaPlayers.size() == 1;
|
boolean last = arenaPlayers.size() == 1;
|
||||||
if (last) lastStanding = p;
|
if (last) lastStanding = p;
|
||||||
|
@ -875,6 +869,19 @@ public class ArenaImpl implements Arena
|
||||||
// Clear the player's inventory, and unmount
|
// Clear the player's inventory, and unmount
|
||||||
if (arenaPlayers.remove(p)) {
|
if (arenaPlayers.remove(p)) {
|
||||||
unmount(p);
|
unmount(p);
|
||||||
|
if (this.keepDrops) {
|
||||||
|
this.inventoryManager.removeOriginalItems(plugin, p);
|
||||||
|
final Step step = histories.get(p);
|
||||||
|
if (step != null) {
|
||||||
|
final Step keepDropsStep = KeepDropsStep.create(this).create(p);
|
||||||
|
keepDropsStep.run();
|
||||||
|
final Step composite = CompositeStep.create(
|
||||||
|
step,
|
||||||
|
keepDropsStep
|
||||||
|
).create(p);
|
||||||
|
histories.put(p, composite);
|
||||||
|
}
|
||||||
|
}
|
||||||
clearInv(p);
|
clearInv(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,7 +933,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin.getServer().getScheduler()
|
plugin.getServer().getScheduler()
|
||||||
.scheduleSyncDelayedTask(plugin, () -> playerLeave(p));
|
.scheduleSyncDelayedTask(plugin, () -> playerLeave(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -961,13 +968,16 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rollback(Player p) {
|
private void rollback(Player p) {
|
||||||
|
|
||||||
Step step = histories.remove(p);
|
Step step = histories.remove(p);
|
||||||
if (step == null) {
|
if (step == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
this.inventoryManager.removeOriginalItems(this.plugin, p);
|
||||||
step.undo();
|
step.undo();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
plugin.getLogger().log(Level.SEVERE, () -> "Failed to revert player " + p.getName());
|
plugin.getLogger().log(Level.SEVERE, () -> "Failed to revert player " + p.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1028,20 +1038,29 @@ public class ArenaImpl implements Arena
|
||||||
|
|
||||||
private EntityType horseTypeFromAmount(int amount) {
|
private EntityType horseTypeFromAmount(int amount) {
|
||||||
switch (amount % 8) {
|
switch (amount % 8) {
|
||||||
case 2: return EntityType.DONKEY;
|
case 2:
|
||||||
case 3: return EntityType.MULE;
|
return EntityType.DONKEY;
|
||||||
case 4: return EntityType.SKELETON_HORSE;
|
case 3:
|
||||||
case 5: return EntityType.ZOMBIE_HORSE;
|
return EntityType.MULE;
|
||||||
default: return EntityType.HORSE;
|
case 4:
|
||||||
|
return EntityType.SKELETON_HORSE;
|
||||||
|
case 5:
|
||||||
|
return EntityType.ZOMBIE_HORSE;
|
||||||
|
default:
|
||||||
|
return EntityType.HORSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Material bardingFromAmount(int amount) {
|
private Material bardingFromAmount(int amount) {
|
||||||
switch ((amount >> 3) % 4) {
|
switch ((amount >> 3) % 4) {
|
||||||
case 1: return Material.IRON_HORSE_ARMOR;
|
case 1:
|
||||||
case 2: return Material.GOLDEN_HORSE_ARMOR;
|
return Material.IRON_HORSE_ARMOR;
|
||||||
case 3: return Material.DIAMOND_HORSE_ARMOR;
|
case 2:
|
||||||
default: return null;
|
return Material.GOLDEN_HORSE_ARMOR;
|
||||||
|
case 3:
|
||||||
|
return Material.DIAMOND_HORSE_ARMOR;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,8 +1120,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeContainerContents()
|
public void storeContainerContents() {
|
||||||
{
|
|
||||||
for (Location loc : region.getContainers()) {
|
for (Location loc : region.getContainers()) {
|
||||||
BlockState state = world.getBlockAt(loc).getState();
|
BlockState state = world.getBlockAt(loc).getState();
|
||||||
if (state instanceof InventoryHolder) {
|
if (state instanceof InventoryHolder) {
|
||||||
|
@ -1112,23 +1130,20 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreContainerContents()
|
public void restoreContainerContents() {
|
||||||
{
|
|
||||||
for (Repairable r : containables) {
|
for (Repairable r : containables) {
|
||||||
r.repair();
|
r.repair();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void discardPlayer(Player p)
|
public void discardPlayer(Player p) {
|
||||||
{
|
|
||||||
rollback(p);
|
rollback(p);
|
||||||
plugin.getArenaMaster().removePlayer(p);
|
plugin.getArenaMaster().removePlayer(p);
|
||||||
clearPlayer(p);
|
clearPlayer(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearPlayer(Player p)
|
private void clearPlayer(Player p) {
|
||||||
{
|
|
||||||
// Remove from boss health bar
|
// Remove from boss health bar
|
||||||
monsterManager.getBossMonsters().forEach(entity -> {
|
monsterManager.getBossMonsters().forEach(entity -> {
|
||||||
MABoss boss = monsterManager.getBoss(entity);
|
MABoss boss = monsterManager.getBoss(entity);
|
||||||
|
@ -1148,15 +1163,13 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void repairBlocks()
|
public void repairBlocks() {
|
||||||
{
|
|
||||||
while (!repairQueue.isEmpty())
|
while (!repairQueue.isEmpty())
|
||||||
repairQueue.poll().repair();
|
repairQueue.poll().repair();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void queueRepairable(Repairable r)
|
public void queueRepairable(Repairable r) {
|
||||||
{
|
|
||||||
repairQueue.add(r);
|
repairQueue.add(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,7 +1184,7 @@ public class ArenaImpl implements Arena
|
||||||
@Override
|
@Override
|
||||||
public void assignClass(Player p, String className) {
|
public void assignClass(Player p, String className) {
|
||||||
ArenaPlayer arenaPlayer = arenaPlayerMap.get(p);
|
ArenaPlayer arenaPlayer = arenaPlayerMap.get(p);
|
||||||
ArenaClass arenaClass = classes.get(className);
|
ArenaClass arenaClass = classes.get(className);
|
||||||
|
|
||||||
if (arenaPlayer == null || arenaClass == null) {
|
if (arenaPlayer == null || arenaClass == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1203,7 +1216,7 @@ public class ArenaImpl implements Arena
|
||||||
@Override
|
@Override
|
||||||
public void assignClassGiveInv(Player p, String className, ItemStack[] source) {
|
public void assignClassGiveInv(Player p, String className, ItemStack[] source) {
|
||||||
ArenaPlayer arenaPlayer = arenaPlayerMap.get(p);
|
ArenaPlayer arenaPlayer = arenaPlayerMap.get(p);
|
||||||
ArenaClass arenaClass = classes.get(className);
|
ArenaClass arenaClass = classes.get(className);
|
||||||
|
|
||||||
if (arenaPlayer == null || arenaClass == null) {
|
if (arenaPlayer == null || arenaClass == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1232,7 +1245,7 @@ public class ArenaImpl implements Arena
|
||||||
ItemStack offhand = null;
|
ItemStack offhand = null;
|
||||||
|
|
||||||
// Check the very last slot to see if it'll work as a helmet
|
// Check the very last slot to see if it'll work as a helmet
|
||||||
int last = contents.length-1;
|
int last = contents.length - 1;
|
||||||
if (contents[last] != null) {
|
if (contents[last] != null) {
|
||||||
helmet = contents[last];
|
helmet = contents[last];
|
||||||
if (arenaClass.hasUnbreakableArmor()) {
|
if (arenaClass.hasUnbreakableArmor()) {
|
||||||
|
@ -1242,7 +1255,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the remaining three of the four last slots for armor
|
// Check the remaining three of the four last slots for armor
|
||||||
for (int i = contents.length-1; i > contents.length-5; i--) {
|
for (int i = contents.length - 1; i > contents.length - 5; i--) {
|
||||||
if (contents[i] == null) continue;
|
if (contents[i] == null) continue;
|
||||||
|
|
||||||
String[] parts = contents[i].getType().name().split("_");
|
String[] parts = contents[i].getType().name().split("_");
|
||||||
|
@ -1255,10 +1268,17 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "ELYTRA":
|
case "ELYTRA":
|
||||||
case "CHESTPLATE": chestplate = stack; break;
|
case "CHESTPLATE":
|
||||||
case "LEGGINGS": leggings = stack; break;
|
chestplate = stack;
|
||||||
case "BOOTS": boots = stack; break;
|
break;
|
||||||
default: break;
|
case "LEGGINGS":
|
||||||
|
leggings = stack;
|
||||||
|
break;
|
||||||
|
case "BOOTS":
|
||||||
|
boots = stack;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
contents[i] = null;
|
contents[i] = null;
|
||||||
}
|
}
|
||||||
|
@ -1320,11 +1340,10 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignRandomClass(Player p)
|
public void assignRandomClass(Player p) {
|
||||||
{
|
|
||||||
List<ArenaClass> classes = this.classes.values().stream()
|
List<ArenaClass> classes = this.classes.values().stream()
|
||||||
.filter(c -> c.hasPermission(p))
|
.filter(c -> c.hasPermission(p))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (classes.isEmpty()) {
|
if (classes.isEmpty()) {
|
||||||
plugin.getLogger().info("Player '" + p.getName() + "' has no class permissions!");
|
plugin.getLogger().info("Player '" + p.getName() + "' has no class permissions!");
|
||||||
|
@ -1354,16 +1373,16 @@ public class ArenaImpl implements Arena
|
||||||
|
|
||||||
private void removePermissionAttachments(Player player) {
|
private void removePermissionAttachments(Player player) {
|
||||||
player.getEffectivePermissions().stream()
|
player.getEffectivePermissions().stream()
|
||||||
.filter(info -> info.getAttachment() != null)
|
.filter(info -> info.getAttachment() != null)
|
||||||
.filter(info -> info.getAttachment().getPlugin().equals(plugin))
|
.filter(info -> info.getAttachment().getPlugin().equals(plugin))
|
||||||
.map(PermissionAttachmentInfo::getAttachment)
|
.map(PermissionAttachmentInfo::getAttachment)
|
||||||
.forEach(PermissionAttachment::remove);
|
.forEach(PermissionAttachment::remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removePotionEffects(Player p) {
|
private void removePotionEffects(Player p) {
|
||||||
p.getActivePotionEffects().stream()
|
p.getActivePotionEffects().stream()
|
||||||
.map(PotionEffect::getType)
|
.map(PotionEffect::getType)
|
||||||
.forEach(p::removePotionEffect);
|
.forEach(p::removePotionEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanup() {
|
private void cleanup() {
|
||||||
|
@ -1423,8 +1442,7 @@ public class ArenaImpl implements Arena
|
||||||
////////////////////////////////////////////////////////////////////*/
|
////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void restoreRegion()
|
public void restoreRegion() {
|
||||||
{
|
|
||||||
Collections.sort(repairables, new RepairableComparator());
|
Collections.sort(repairables, new RepairableComparator());
|
||||||
|
|
||||||
for (Repairable r : repairables)
|
for (Repairable r : repairables)
|
||||||
|
@ -1460,14 +1478,12 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String configName()
|
public String configName() {
|
||||||
{
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String arenaName()
|
public String arenaName() {
|
||||||
{
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1477,26 +1493,22 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MobArena getPlugin()
|
public MobArena getPlugin() {
|
||||||
{
|
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String,ArenaClass> getClasses()
|
public Map<String, ArenaClass> getClasses() {
|
||||||
{
|
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPlayerCount()
|
public int getPlayerCount() {
|
||||||
{
|
|
||||||
return spawnThread.getPlayerCount();
|
return spawnThread.getPlayerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Player> getAllPlayers()
|
public List<Player> getAllPlayers() {
|
||||||
{
|
|
||||||
List<Player> result = new LinkedList<>();
|
List<Player> result = new LinkedList<>();
|
||||||
result.addAll(arenaPlayers);
|
result.addAll(arenaPlayers);
|
||||||
result.addAll(lobbyPlayers);
|
result.addAll(lobbyPlayers);
|
||||||
|
@ -1506,8 +1518,7 @@ public class ArenaImpl implements Arena
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<ArenaPlayer> getArenaPlayerSet()
|
public Collection<ArenaPlayer> getArenaPlayerSet() {
|
||||||
{
|
|
||||||
return arenaPlayerMap.values();
|
return arenaPlayerMap.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1529,8 +1540,7 @@ public class ArenaImpl implements Arena
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Player> getNonreadyPlayers()
|
public List<Player> getNonreadyPlayers() {
|
||||||
{
|
|
||||||
List<Player> result = new LinkedList<>();
|
List<Player> result = new LinkedList<>();
|
||||||
result.addAll(lobbyPlayers);
|
result.addAll(lobbyPlayers);
|
||||||
result.removeAll(readyPlayers);
|
result.removeAll(readyPlayers);
|
||||||
|
@ -1636,7 +1646,7 @@ public class ArenaImpl implements Arena
|
||||||
if (getClass() != other.getClass()) return false;
|
if (getClass() != other.getClass()) return false;
|
||||||
|
|
||||||
// Arenas must have different names.
|
// Arenas must have different names.
|
||||||
if (other instanceof ArenaImpl && ((ArenaImpl)other).name.equals(name))
|
if (other instanceof ArenaImpl && ((ArenaImpl) other).name.equals(name))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.garbagemule.MobArena.formula;
|
package com.garbagemule.MobArena.formula;
|
||||||
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface BinaryOperation extends BiFunction<Double, Double, Double> {
|
public interface BinaryOperation {
|
||||||
|
|
||||||
|
double apply(double left, double right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.garbagemule.MobArena.formula;
|
package com.garbagemule.MobArena.formula;
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface UnaryOperation extends Function<Double, Double> {
|
public interface UnaryOperation {
|
||||||
|
|
||||||
|
double apply(double value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public interface Arena
|
||||||
|
|
||||||
int getMaxPlayers();
|
int getMaxPlayers();
|
||||||
|
|
||||||
|
boolean isKeepDrops();
|
||||||
|
|
||||||
List<Thing> getEntryFee();
|
List<Thing> getEntryFee();
|
||||||
|
|
||||||
Set<Map.Entry<Integer, ThingPicker>> getEveryWaveEntrySet();
|
Set<Map.Entry<Integer, ThingPicker>> getEveryWaveEntrySet();
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.garbagemule.MobArena.steps;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class CompositeStep extends PlayerStep {
|
||||||
|
|
||||||
|
private final Step original;
|
||||||
|
private final Step next;
|
||||||
|
|
||||||
|
|
||||||
|
private CompositeStep(Player player, Step original, Step next) {
|
||||||
|
super(player);
|
||||||
|
this.original = original;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
this.original.run();
|
||||||
|
this.next.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo() {
|
||||||
|
this.original.undo();
|
||||||
|
this.next.undo();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static StepFactory create(Step original, Step next) {
|
||||||
|
return player -> new CompositeStep(player, original, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.garbagemule.MobArena.steps;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class KeepDropsStep extends PlayerStep {
|
||||||
|
|
||||||
|
private final File keepDrops;
|
||||||
|
private final Arena arena;
|
||||||
|
|
||||||
|
private ItemStack[] contents;
|
||||||
|
private File backup;
|
||||||
|
|
||||||
|
private KeepDropsStep(Player player, Arena arena) {
|
||||||
|
super(player);
|
||||||
|
this.keepDrops = new File(arena.getPlugin().getDataFolder(), "extra-drops");
|
||||||
|
this.arena = arena;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
contents = player.getInventory().getContents();
|
||||||
|
createBackup();
|
||||||
|
|
||||||
|
player.getInventory().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void undo() {
|
||||||
|
for (ItemStack itemStack : contents) {
|
||||||
|
if (itemStack == null) continue;
|
||||||
|
player.getInventory().addItem(itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
arena.getInventoryManager().removeKeepDrops(player);
|
||||||
|
deleteBackup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createBackup() {
|
||||||
|
arena.getInventoryManager().removeOriginalItems(arena.getPlugin(), player);
|
||||||
|
YamlConfiguration yaml = new YamlConfiguration();
|
||||||
|
yaml.set("contents", contents);
|
||||||
|
|
||||||
|
backup = new File(keepDrops, player.getUniqueId().toString());
|
||||||
|
try {
|
||||||
|
yaml.save(backup);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Failed to store keep-drops for " + player.getName(), e);
|
||||||
|
}
|
||||||
|
arena.getInventoryManager().putKeepDrops(player, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteBackup() {
|
||||||
|
try {
|
||||||
|
Files.delete(backup.toPath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
arena.getPlugin().getLogger().log(Level.WARNING, "Couldn't delete backup inventory file for " + player.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StepFactory create(Arena arena) {
|
||||||
|
return player -> new KeepDropsStep(player, arena);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import org.bukkit.World;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class InventoryThingParser implements ThingParser {
|
class InventoryThingParser implements ThingParser {
|
||||||
|
|
||||||
private static final String PREFIX = "inv(";
|
private static final String PREFIX = "inv(";
|
||||||
private static final String SUFFIX = ")";
|
private static final String SUFFIX = ")";
|
||||||
|
|
|
@ -10,21 +10,17 @@ public class ThingManager implements ThingParser {
|
||||||
private final List<ThingParser> parsers;
|
private final List<ThingParser> parsers;
|
||||||
private final ItemStackThingParser items;
|
private final ItemStackThingParser items;
|
||||||
|
|
||||||
public ThingManager(MobArena plugin, ItemStackThingParser parser) {
|
public ThingManager(MobArena plugin) {
|
||||||
parsers = new ArrayList<>();
|
parsers = new ArrayList<>();
|
||||||
parsers.add(new CommandThingParser());
|
parsers.add(new CommandThingParser());
|
||||||
parsers.add(new MoneyThingParser(plugin));
|
parsers.add(new MoneyThingParser(plugin));
|
||||||
parsers.add(new PermissionThingParser(plugin));
|
parsers.add(new PermissionThingParser(plugin));
|
||||||
parsers.add(new PotionEffectThingParser());
|
parsers.add(new PotionEffectThingParser());
|
||||||
parsers.add(new InventoryThingParser(plugin.getServer()));
|
parsers.add(new InventoryThingParser(plugin.getServer()));
|
||||||
items = parser;
|
items = new ItemStackThingParser();
|
||||||
items.register(new SavedItemParser(plugin));
|
items.register(new SavedItemParser(plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThingManager(MobArena plugin) {
|
|
||||||
this(plugin, new ItemStackThingParser());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new thing parser in the manager.
|
* Register a new thing parser in the manager.
|
||||||
*
|
*
|
||||||
|
|
|
@ -2,12 +2,15 @@ package com.garbagemule.MobArena.util.inventory;
|
||||||
|
|
||||||
import com.garbagemule.MobArena.MobArena;
|
import com.garbagemule.MobArena.MobArena;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.InventoryView;
|
import org.bukkit.inventory.InventoryView;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.PlayerInventory;
|
import org.bukkit.inventory.PlayerInventory;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -16,16 +19,28 @@ import java.util.logging.Level;
|
||||||
|
|
||||||
public class InventoryManager
|
public class InventoryManager
|
||||||
{
|
{
|
||||||
|
private static final String ORIGINAL_ITEM_KEY = "original-item";
|
||||||
|
|
||||||
private Map<Player, ItemStack[]> inventories;
|
private Map<Player, ItemStack[]> inventories;
|
||||||
|
private Map<Player, ItemStack[]> keepDrops;
|
||||||
|
|
||||||
public InventoryManager() {
|
public InventoryManager() {
|
||||||
this.inventories = new HashMap<>();
|
this.inventories = new HashMap<>();
|
||||||
|
this.keepDrops = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void put(Player p, ItemStack[] contents) {
|
public void put(Player p, ItemStack[] contents) {
|
||||||
inventories.put(p, contents);
|
inventories.put(p, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void putKeepDrops(Player p, ItemStack[] contents) {
|
||||||
|
keepDrops.put(p, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack[] getKeepDrops(Player p) {
|
||||||
|
return keepDrops.get(p);
|
||||||
|
}
|
||||||
|
|
||||||
public void equip(Player p) {
|
public void equip(Player p) {
|
||||||
ItemStack[] contents = inventories.get(p);
|
ItemStack[] contents = inventories.get(p);
|
||||||
if (contents == null) {
|
if (contents == null) {
|
||||||
|
@ -34,10 +49,44 @@ public class InventoryManager
|
||||||
p.getInventory().setContents(contents);
|
p.getInventory().setContents(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets PDC on the player's items from when they first joined the arena
|
||||||
|
* So that item drops in the arena can be kept when they leave
|
||||||
|
*/
|
||||||
|
public void setOriginalItemsPDC(MobArena plugin, Player player) {
|
||||||
|
final NamespacedKey key = new NamespacedKey(plugin, ORIGINAL_ITEM_KEY);
|
||||||
|
for (ItemStack itemStack : player.getInventory().getContents()) {
|
||||||
|
if (itemStack == null) continue;
|
||||||
|
final ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
if (itemMeta == null) continue;
|
||||||
|
itemMeta.getPersistentDataContainer().set(key, PersistentDataType.BYTE, (byte) 1);
|
||||||
|
itemStack.setItemMeta(itemMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOriginalItems(MobArena plugin, Player player) {
|
||||||
|
final NamespacedKey key = new NamespacedKey(plugin, ORIGINAL_ITEM_KEY);
|
||||||
|
final ItemStack[] contents = player.getInventory().getContents();
|
||||||
|
for (int i = 0; i < contents.length; i++) {
|
||||||
|
final ItemStack itemStack = contents[i];
|
||||||
|
if (itemStack == null) continue;
|
||||||
|
final ItemMeta itemMeta = itemStack.getItemMeta();
|
||||||
|
if (itemMeta == null) continue;
|
||||||
|
if (itemMeta.getPersistentDataContainer().has(key, PersistentDataType.BYTE)) {
|
||||||
|
itemStack.setType(Material.AIR);
|
||||||
|
player.getInventory().clear(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void remove(Player p) {
|
public void remove(Player p) {
|
||||||
inventories.remove(p);
|
inventories.remove(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeKeepDrops(Player p) {
|
||||||
|
keepDrops.remove(p);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear a player's inventory completely.
|
* Clear a player's inventory completely.
|
||||||
* @param p a player
|
* @param p a player
|
||||||
|
@ -83,6 +132,8 @@ public class InventoryManager
|
||||||
File inventories = new File(plugin.getDataFolder(), "inventories");
|
File inventories = new File(plugin.getDataFolder(), "inventories");
|
||||||
File file = new File(inventories, p.getUniqueId().toString());
|
File file = new File(inventories, p.getUniqueId().toString());
|
||||||
|
|
||||||
|
restoreKeepDrops(plugin, p);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -100,4 +151,25 @@ public class InventoryManager
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void restoreKeepDrops(MobArena plugin, Player p) {
|
||||||
|
try {
|
||||||
|
File inventories = new File(plugin.getDataFolder(), "keep-drops");
|
||||||
|
File file = new File(inventories, p.getUniqueId().toString());
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
YamlConfiguration config = new YamlConfiguration();
|
||||||
|
config.load(file);
|
||||||
|
|
||||||
|
ItemStack[] contents = config.getList("extra-drops").toArray(new ItemStack[0]);
|
||||||
|
p.getInventory().addItem(contents);
|
||||||
|
|
||||||
|
file.delete();
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.getLogger().log(Level.SEVERE, "Failed to restore extra drops for " + p.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ author: garbagemule
|
||||||
main: com.garbagemule.MobArena.MobArena
|
main: com.garbagemule.MobArena.MobArena
|
||||||
version: '${project.version}'
|
version: '${project.version}'
|
||||||
api-version: 1.13
|
api-version: 1.13
|
||||||
softdepend: [Multiverse-Core,Towny,Heroes,MagicSpells,Vault]
|
softdepend: [Multiverse-Core,Towny,Heroes,MagicSpells,Vault,AdvancedEnchantments]
|
||||||
|
loadbefore: [AdvancedEnchantments]
|
||||||
commands:
|
commands:
|
||||||
ma:
|
ma:
|
||||||
description: Base command for MobArena
|
description: Base command for MobArena
|
||||||
|
|
|
@ -45,6 +45,7 @@ display-waves-as-level: false
|
||||||
display-timer-as-level: false
|
display-timer-as-level: false
|
||||||
use-scoreboards: true
|
use-scoreboards: true
|
||||||
isolated-chat: false
|
isolated-chat: false
|
||||||
|
keep-drops: false
|
||||||
announcer-type: title
|
announcer-type: title
|
||||||
global-join-announce: false
|
global-join-announce: false
|
||||||
global-end-announce: false
|
global-end-announce: false
|
||||||
|
|
|
@ -230,8 +230,8 @@ public class FormulaManagerIT {
|
||||||
@Parameters(name = "{0} = {1}")
|
@Parameters(name = "{0} = {1}")
|
||||||
public static Iterable<Object[]> data() {
|
public static Iterable<Object[]> data() {
|
||||||
return Arrays.asList(new Object[][]{
|
return Arrays.asList(new Object[][]{
|
||||||
{"1 + +1.2", 1 + +1.2},
|
{"1 + +1.2", 1 + 1.2},
|
||||||
{"1 + -1.2", 1 + -1.2},
|
{"1 + -1.2", 1 + (-1.2)},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,8 +259,8 @@ public class FormulaManagerIT {
|
||||||
@Parameters(name = "{0} = {1}")
|
@Parameters(name = "{0} = {1}")
|
||||||
public static Iterable<Object[]> data() {
|
public static Iterable<Object[]> data() {
|
||||||
return Arrays.asList(new Object[][]{
|
return Arrays.asList(new Object[][]{
|
||||||
{"1+-2", 1 + -2},
|
{"1+-2", 1 + (-2)},
|
||||||
{"3-+4", 3 - +4},
|
{"3-+4", 3 - 4},
|
||||||
{"3*7.5", 3 * 7.5},
|
{"3*7.5", 3 * 7.5},
|
||||||
{"10/2.5", 10 / 2.5},
|
{"10/2.5", 10 / 2.5},
|
||||||
{"9%4", 9 % 4},
|
{"9%4", 9 % 4},
|
||||||
|
|
|
@ -6,7 +6,7 @@ import org.hamcrest.TypeSafeMatcher;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class LexemeMatcher extends TypeSafeMatcher<Lexeme> {
|
class LexemeMatcher extends TypeSafeMatcher<Lexeme> {
|
||||||
|
|
||||||
private final TokenType type;
|
private final TokenType type;
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
Loading…
Reference in New Issue