Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b97fe7e5b1 | |||
| 01db4fa951 | |||
|
cb153b50f1
|
|||
|
8b33bf40c3
|
|||
| 9a6221b723 | |||
|
a20b1cb263
|
|||
|
cfe6055083
|
|||
|
eea9abdc56
|
|||
| 138b94e562 | |||
|
d11467bd1b
|
|||
| 7be40d9bf9 | |||
|
dae8073992
|
|||
|
143e7dc17c
|
|||
| f4ace64173 | |||
|
236b486845
|
|||
|
c666f0228d
|
|||
| 81049856b5 | |||
| 4813e24848 | |||
| d61d001ddf | |||
| 060364abb5 | |||
| 13185f0e05 | |||
| fd266969f5 | |||
| bd471330e1 | |||
|
92602efa9e
|
|||
|
55a39ac85a
|
|||
|
39898825ef
|
|||
| 59a2d1454e | |||
|
16c324cf32
|
|||
|
b923b98b2c
|
|||
| afca7d5135 | |||
|
a05bebcd81
|
|||
|
02cc8330ca
|
|||
|
f8397b8bab
|
|||
| 38603fbe45 | |||
|
78700e868d
|
|||
|
259e8bdb7b
|
|||
| 0ea3c25b7b | |||
|
2fa1b7d329
|
|||
| af805f6ba4 | |||
|
34c361d3f8
|
|||
| 83eb621b0f | |||
|
65aaf4857d
|
|||
| 7d52447b00 | |||
| 046ab8d1a8 | |||
|
33c032092d
|
|||
| b8eeb93a8f | |||
|
e95f68406f
|
|||
|
c6f432a5c4
|
|||
| 9ca7446dba | |||
| 773a1adf64 | |||
|
6afe5d4c0d
|
|||
|
755a05fe34
|
|||
|
202da658ee
|
|||
| a5856cf240 | |||
|
38099e6167
|
|||
|
d307038e5e
|
|||
|
d5aeeaf5e3
|
|||
|
134a05ea23
|
|||
|
db63f2a67c
|
|||
| 97a3c3ef35 | |||
| a40e904ab3 | |||
| a8a89b0809 | |||
|
480efd1f8b
|
|||
| 26baccf3c4 | |||
| 916f9b2557 | |||
| 34992344b2 | |||
| 1ea8dea381 | |||
| 15aa0572f3 | |||
|
6a843f4a71
|
|||
|
a63c1a94ca
|
|||
| 43263035d9 | |||
|
42ab55d0f8
|
|||
|
44846cce57
|
|||
|
1451750bcb
|
|||
| 8ade5180cb | |||
| d0535d0c47 | |||
| 79fa09e39b | |||
|
4010c2125c
|
|||
| 32de0077de | |||
| bd53e016c5 | |||
| 5b1ed644d1 | |||
| a41787d89d | |||
| 8e392b56c3 | |||
| 42feadcd2d | |||
| 15f0344416 | |||
| c90a977ab2 | |||
| b186228f4e | |||
| 5f38474809 | |||
| 4f27320548 | |||
| ba7bd1f1dd | |||
| fbe70e7ead | |||
| 30a499be1d | |||
|
86e212fe42
|
|||
| 4a646e6be0 | |||
| bc0dc1925e | |||
| c3af4dbc68 | |||
| 703639537d | |||
| 9ac3bf6a6c | |||
| 41ea6c9407 | |||
| 67e9a3544e | |||
| f69ae3e77b | |||
|
2208dcc0fb
|
|||
| b466216b3a | |||
| 5a862b251b | |||
| 60a82a685d | |||
| 573b0c14ae | |||
| 82abe7e20f | |||
| 34da59714e | |||
| 97071165cd | |||
| 634465fbf1 | |||
| 2ad8cc3f4a | |||
| e190fe0858 | |||
| 569d91a0d3 | |||
| 487a15849a | |||
| e110033315 | |||
| c0b192e2bf | |||
| 612254296c | |||
|
1dbcb122c2
|
|||
|
f2ee9dbeb3
|
|||
| 404ab2abfb | |||
| 59a927c33c | |||
|
6c062216a1
|
|||
| 72d62dfbe5 | |||
| 76ecaccc41 | |||
| 9587b9e1fd | |||
| 14dc807fd9 | |||
| 63ad85f727 | |||
| 72e88502d2 | |||
| 71767ef6d9 | |||
| 73f903fc23 | |||
|
25116c3865
|
|||
|
22ed7e23da
|
|||
|
c0163d813e
|
@@ -0,0 +1,60 @@
|
||||
name: Bug Report
|
||||
about: Du hast einen Fehler gefunden? Melde ihn hier!
|
||||
labels: [ "typ/bug" ]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
ACHTUNG: Sollte es bei dem Bug ein Sicherheitsrisiko geben, melde es bitte auf unserem Discord Server
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: |
|
||||
Beschreibe deinen Bug in kurzer Form.
|
||||
- type: input
|
||||
id: mc-ver
|
||||
attributes:
|
||||
label: Minecraft Version
|
||||
description: Minecraft Version des Clients
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: mc-ver-ser
|
||||
attributes:
|
||||
label: Minecraft Version Server
|
||||
description: Minecraft Version des Servers, nur bei Bau oder Arenen Servern
|
||||
- type: dropdown
|
||||
id: can-reproduce
|
||||
attributes:
|
||||
label: Kannst du den Fehler wiederholen?
|
||||
description: |
|
||||
Wenn du den Fehler wiederholen kannst, können wir dieses Problem schneller beheben.
|
||||
Solltest du den Fehler nicht wiederholen können, melde dich bitte auf unserem Discord Server.
|
||||
options:
|
||||
- "Yes"
|
||||
- "No"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduce-steps
|
||||
attributes:
|
||||
label: Wie kannst du den Fehler wiederholen?
|
||||
description: Welche Schritte musst du ausführen, um den Fehler wiederholen zu können?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-result
|
||||
attributes:
|
||||
label: Was sollte passieren?
|
||||
description: Was sollte hier deiner Erwartung nach passieren?
|
||||
- type: input
|
||||
id: logs
|
||||
attributes:
|
||||
label: Auf welchem Server ist der Fehler aufgetreten?
|
||||
description: Gebe bitte den Namen des Servers an, auf dem der Fehler aufgetreten ist. z.B. "Lobby", "Lixfels Bauserver" etc.
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: Sollte es ein Visuelles Problem geben, kannst du hier Screenshots hinzufügen.
|
||||
@@ -0,0 +1 @@
|
||||
blank_issues_enabled: true
|
||||
@@ -0,0 +1,17 @@
|
||||
name: Feature Idee
|
||||
about: Du hast eine Idee für ein neues Feature, welches SteamWar nicht hat? Stelle sie hier vor.
|
||||
labels: ["typ/idee"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Feature Beschreibung
|
||||
placeholder: |
|
||||
Ich glaube, dass ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: Wenn es sich um etwas grafisches handelt, kannst du hier Screenshots hinzufügen.
|
||||
@@ -0,0 +1,193 @@
|
||||
name: Backport CommonCore
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
BACKPORT_PATH: CommonCore
|
||||
BACKPORT_BRANCH_PREFIX: backport/commoncore
|
||||
DISABLE_BACKPORT_LABEL: no-backport
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
name: Create CommonCore backport PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check backport eligibility
|
||||
id: eligibility
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
api_url="${GITHUB_API_URL:-${GITHUB_SERVER_URL}/api/v1}"
|
||||
|
||||
echo "Backport debug: event=${GITHUB_EVENT_NAME:-unknown}"
|
||||
echo "Backport debug: server=${GITHUB_SERVER_URL}"
|
||||
echo "Backport debug: api=${api_url}"
|
||||
echo "Backport debug: repository=${GITHUB_REPOSITORY}"
|
||||
echo "Backport debug: action=$(jq -r '.action // ""' "$GITHUB_EVENT_PATH")"
|
||||
|
||||
merged="$(jq -r '.pull_request.merged // (.pull_request.merged_at != null)' "$GITHUB_EVENT_PATH")"
|
||||
base_branch="$(jq -r '.pull_request.base.ref' "$GITHUB_EVENT_PATH")"
|
||||
has_disable_label="$(jq -r --arg disable_backport_label "$DISABLE_BACKPORT_LABEL" 'any(.pull_request.labels[]?; .name == $disable_backport_label)' "$GITHUB_EVENT_PATH")"
|
||||
echo "Backport debug: pr=$(jq -r '.pull_request.number // ""' "$GITHUB_EVENT_PATH") base=${base_branch} merged=${merged}"
|
||||
echo "Backport debug: disable label present=${has_disable_label}"
|
||||
|
||||
{
|
||||
echo "should_backport=$([[ "$merged" == "true" && "$base_branch" == "main" && "$has_disable_label" != "true" ]] && echo true || echo false)"
|
||||
echo "pr_number=$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH")"
|
||||
echo "pr_title<<EOF"
|
||||
jq -r '.pull_request.title' "$GITHUB_EVENT_PATH"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
labels="$(curl -fsS \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
||||
"${api_url}/repos/${GITHUB_REPOSITORY}/labels")"
|
||||
|
||||
if ! jq -e --arg disable_backport_label "$DISABLE_BACKPORT_LABEL" 'any(.[]; .name == $disable_backport_label)' <<< "$labels" >/dev/null; then
|
||||
curl -fsS -X POST \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -n --arg name "$DISABLE_BACKPORT_LABEL" --arg color "ededed" --arg description "Disable automatic CommonCore backporting for this pull request." '{name: $name, color: $color, description: $description}')" \
|
||||
"${api_url}/repos/${GITHUB_REPOSITORY}/labels"
|
||||
fi
|
||||
|
||||
- name: Create backport pull requests
|
||||
if: steps.eligibility.outputs.should_backport == 'true'
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
|
||||
PR_NUMBER: ${{ steps.eligibility.outputs.pr_number }}
|
||||
PR_TITLE: ${{ steps.eligibility.outputs.pr_title }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
api_url="${GITHUB_API_URL:-${GITHUB_SERVER_URL}/api/v1}"
|
||||
repo_api_path="/repos/${GITHUB_REPOSITORY}"
|
||||
|
||||
api_request() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local output="$3"
|
||||
local data_file="${4:-}"
|
||||
local status
|
||||
local args=(-sS -X "$method" -H "Accept: application/json" -H "Authorization: token ${GITHUB_TOKEN}" -w "%{http_code}" -o "$output")
|
||||
|
||||
if [[ -n "$data_file" ]]; then
|
||||
args+=(-H "Content-Type: application/json" --data-binary "@${data_file}")
|
||||
fi
|
||||
|
||||
echo "Backport debug: ${method} ${path}"
|
||||
if ! status="$(curl "${args[@]}" "${api_url}${path}")"; then
|
||||
echo "Backport debug: ${method} ${path} failed before HTTP status was captured."
|
||||
if [[ -s "$output" ]]; then
|
||||
echo "Backport debug: response body:"
|
||||
cat "$output"
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Backport debug: ${method} ${path} -> HTTP ${status}"
|
||||
if [[ ! "$status" =~ ^2 ]]; then
|
||||
echo "Backport debug: response body:"
|
||||
cat "$output"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Backport debug: event=${GITHUB_EVENT_NAME:-unknown}"
|
||||
echo "Backport debug: server=${GITHUB_SERVER_URL}"
|
||||
echo "Backport debug: api=${api_url}"
|
||||
echo "Backport debug: repository=${GITHUB_REPOSITORY}"
|
||||
echo "Backport debug: pr=${PR_NUMBER}"
|
||||
echo "Backport debug: actor=${GITHUB_ACTOR:-unknown}"
|
||||
|
||||
git config user.name "SteamWar Backport Bot"
|
||||
git config user.email "actions@steamwar.de"
|
||||
|
||||
if [[ "${GITHUB_SERVER_URL}" == https://* ]]; then
|
||||
auth_host="${GITHUB_SERVER_URL#https://}"
|
||||
git remote set-url origin "https://oauth2:${GITHUB_TOKEN}@${auth_host}/${GITHUB_REPOSITORY}.git"
|
||||
fi
|
||||
|
||||
git fetch --prune origin '+refs/heads/version/*:refs/remotes/origin/version/*'
|
||||
|
||||
api_request GET "${repo_api_path}" repo-debug.json
|
||||
jq -r '"Backport debug: repo permissions admin=\(.permissions.admin // "unknown") push=\(.permissions.push // "unknown") pull=\(.permissions.pull // "unknown")"' repo-debug.json || true
|
||||
|
||||
echo "Backport debug: GET ${repo_api_path}/pulls/${PR_NUMBER}.diff"
|
||||
curl -fsSL -w "Backport debug: GET ${repo_api_path}/pulls/${PR_NUMBER}.diff -> HTTP %{http_code}\n" \
|
||||
-H "Accept: text/plain" \
|
||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
||||
"${api_url}${repo_api_path}/pulls/${PR_NUMBER}.diff" \
|
||||
-o pull-request.diff
|
||||
|
||||
if ! grep -Eq "^diff --git a/${BACKPORT_PATH}/" pull-request.diff; then
|
||||
echo "Pull request #${PR_NUMBER} has no ${BACKPORT_PATH} changes to backport."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mapfile -t target_branches < <(git for-each-ref --format='%(refname:strip=3)' refs/remotes/origin/version)
|
||||
if [[ "${#target_branches[@]}" -eq 0 ]]; then
|
||||
echo "No version/* branches found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for target_branch in "${target_branches[@]}"; do
|
||||
safe_target="${target_branch//\//-}"
|
||||
backport_branch="${BACKPORT_BRANCH_PREFIX}/pr-${PR_NUMBER}-to-${safe_target}"
|
||||
|
||||
git checkout -B "${backport_branch}" "origin/${target_branch}"
|
||||
git reset --hard "origin/${target_branch}"
|
||||
|
||||
if ! git apply --3way --index --include="${BACKPORT_PATH}/**" pull-request.diff; then
|
||||
echo "Failed to apply CommonCore backport for ${target_branch}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "CommonCore changes from #${PR_NUMBER} are already present in ${target_branch}."
|
||||
continue
|
||||
fi
|
||||
|
||||
git commit -m "Backport CommonCore changes from #${PR_NUMBER}" -m "${PR_TITLE}"
|
||||
git push --force-with-lease origin "${backport_branch}"
|
||||
|
||||
api_request GET "${repo_api_path}/pulls?state=open" open-pulls.json
|
||||
open_pr_number="$(jq -r --arg base "$target_branch" --arg head "$backport_branch" '[.[] | select(.base.ref == $base and .head.ref == $head) | (.number // .index)][0] // empty' open-pulls.json)"
|
||||
|
||||
if [[ -n "$open_pr_number" ]]; then
|
||||
echo "Backport PR #${open_pr_number} already exists for ${target_branch}."
|
||||
continue
|
||||
fi
|
||||
|
||||
pr_body="$(printf 'Automatic CommonCore backport of #%s.\n\nOriginal PR title: %s\n\nOnly files below `CommonCore/` are included.' "$PR_NUMBER" "$PR_TITLE")"
|
||||
|
||||
jq -n \
|
||||
--arg base "$target_branch" \
|
||||
--arg head "$backport_branch" \
|
||||
--arg title "Backport CommonCore changes from #${PR_NUMBER} to ${target_branch}" \
|
||||
--arg body "$pr_body" \
|
||||
'{base: $base, head: $head, title: $title, body: $body}' > create-pull.json
|
||||
|
||||
echo "Backport debug: create PR base=${target_branch} head=${backport_branch}"
|
||||
api_request POST "${repo_api_path}/pulls" create-pull-response.json create-pull.json
|
||||
done
|
||||
@@ -0,0 +1,145 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- version/*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v6
|
||||
- name: Setup Java 8
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
- name: Setup Java 17
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
- name: Setup Maven Repository
|
||||
env:
|
||||
SW_MAVEN_CREDENTIALS: ${{ secrets.SW_MAVEN_CREDENTIALS }}
|
||||
run: |
|
||||
echo "$SW_MAVEN_CREDENTIALS" > steamwar.properties
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build --no-daemon
|
||||
|
||||
- name: Stage deploy artifacts
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
rm -rf deploy
|
||||
mkdir -p deploy
|
||||
|
||||
cp "BauSystem/build/libs/BauSystem-all.jar" "deploy/BauSystem.jar"
|
||||
cp "LegacyBauSystem/build/libs/LegacyBauSystem.jar" "deploy/BauSystem-1.12.jar"
|
||||
cp "FightSystem/build/libs/FightSystem-all.jar" "deploy/FightSystem.jar"
|
||||
cp "KotlinCore/build/libs/KotlinCore-all.jar" "deploy/KotlinCore.jar"
|
||||
cp "TNTLeague/build/libs/TNTLeague.jar" "deploy/TNTLeague.jar"
|
||||
cp "LobbySystem/build/libs/LobbySystem.jar" "deploy/LobbySystem.jar"
|
||||
cp "MissileWars/build/libs/MissileWars.jar" "deploy/MissileWars.jar"
|
||||
cp "Realtime/build/libs/Realtime.jar" "deploy/RealTime.jar"
|
||||
cp "SchematicSystem/build/libs/SchematicSystem-all.jar" "deploy/SchematicSystem.jar"
|
||||
cp "SpigotCore/build/libs/SpigotCore-all.jar" "deploy/SpigotCore.jar"
|
||||
cp "Teamserver/build/libs/Teamserver.jar" "deploy/Builder.jar"
|
||||
cp "TowerRun/build/libs/TowerRun.jar" "deploy/TowerRun.jar"
|
||||
cp "VelocityCore/Persistent/build/libs/Persistent.jar" "deploy/PersistentVelocityCore.jar"
|
||||
cp "VelocityCore/Dependencies/build/libs/Dependencies-all.jar" "deploy/DependenciesVelocityCore.jar"
|
||||
cp "VelocityCore/build/libs/VelocityCore-all.jar" "deploy/VelocityCore.jar"
|
||||
cp "WebsiteBackend/build/libs/WebsiteBackend-all.jar" "deploy/website-api.jar"
|
||||
cp "CLI/build/distributions/sw.zip" "deploy/sw.zip"
|
||||
|
||||
- name: Upload deploy artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: steamwar-jars
|
||||
path: deploy/
|
||||
|
||||
deploy:
|
||||
name: Deploy
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Download deploy artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: steamwar-jars
|
||||
path: deploy
|
||||
|
||||
- name: Resolve deploy target
|
||||
id: target
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${GITHUB_REF_NAME}" == "main" ]]; then
|
||||
echo "path=/jars/current" >> "$GITHUB_OUTPUT"
|
||||
elif [[ "${GITHUB_REF_NAME}" == version/* ]]; then
|
||||
version="${GITHUB_REF_NAME#version/}"
|
||||
if [[ ! "$version" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
||||
echo "Unsupported version branch name: ${GITHUB_REF_NAME}" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "path=/jars/${version}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "Unsupported deployment branch: ${GITHUB_REF_NAME}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Upload jars with scp
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
DEPLOY_PATH: ${{ steps.target.outputs.path }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
: "${DEPLOY_HOST:?Missing DEPLOY_HOST secret}"
|
||||
: "${DEPLOY_USER:?Missing DEPLOY_USER secret}"
|
||||
: "${DEPLOY_SSH_KEY:?Missing DEPLOY_SSH_KEY secret}"
|
||||
|
||||
port="${DEPLOY_PORT:-22}"
|
||||
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
echo "$DEPLOY_SSH_KEY" > ~/.ssh/deploy_key
|
||||
chmod 600 ~/.ssh/deploy_key
|
||||
ssh-keyscan -p "$port" "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
||||
|
||||
ssh -i ~/.ssh/deploy_key -p "$port" "${DEPLOY_USER}@${DEPLOY_HOST}" "mkdir -p '$DEPLOY_PATH'"
|
||||
scp -i ~/.ssh/deploy_key -P "$port" deploy/* "${DEPLOY_USER}@${DEPLOY_HOST}:$DEPLOY_PATH/"
|
||||
- name: Restart Services
|
||||
shell: bash
|
||||
env:
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
ssh -i ~/.ssh/deploy_key -p "$DEPLOY_PORT" "${DEPLOY_USER}@${DEPLOY_HOST}" "sudo systemctl restart api.service"
|
||||
ssh -i ~/.ssh/deploy_key -p "$DEPLOY_PORT" "${DEPLOY_USER}@${DEPLOY_HOST}" "unzip -o /jars/current/sw.zip -d /jars"
|
||||
@@ -0,0 +1,76 @@
|
||||
name: Pull Request Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v6
|
||||
- name: Setup Java 8
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 8
|
||||
- name: Setup Java 11
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 11
|
||||
- name: Setup Java 17
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
- name: Setup Maven Repository
|
||||
env:
|
||||
SW_MAVEN_CREDENTIALS: ${{ secrets.SW_MAVEN_CREDENTIALS }}
|
||||
run: |
|
||||
echo "$SW_MAVEN_CREDENTIALS" > steamwar.properties
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build --no-daemon
|
||||
|
||||
- name: Merge successful backport PR
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
|
||||
BACKPORT_BRANCH_PREFIX: backport/commoncore
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
head_branch="$(jq -r '.pull_request.head.ref // ""' "$GITHUB_EVENT_PATH")"
|
||||
base_branch="$(jq -r '.pull_request.base.ref // ""' "$GITHUB_EVENT_PATH")"
|
||||
pr_number="$(jq -r '.pull_request.number' "$GITHUB_EVENT_PATH")"
|
||||
|
||||
if [[ "${head_branch}" != "${BACKPORT_BRANCH_PREFIX}/"* ]]; then
|
||||
echo "Not a CommonCore backport PR."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${base_branch}" != version/* ]]; then
|
||||
echo "Backport PR target is not a version/* branch."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
api_url="${GITHUB_API_URL:-${GITHUB_SERVER_URL}/api/v1}"
|
||||
|
||||
curl -fsS -X POST \
|
||||
-H "Accept: application/json" \
|
||||
-H "Authorization: token ${GITHUB_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"Do":"merge","delete_branch_after_merge":true}' \
|
||||
"${api_url}/repos/${GITHUB_REPOSITORY}/pulls/${pr_number}/merge"
|
||||
+1
-1
@@ -21,4 +21,4 @@ lib
|
||||
/WebsiteBackend/logs
|
||||
/WebsiteBackend/skins
|
||||
/WebsiteBackend/config.json
|
||||
/WebsiteBackend/sessions
|
||||
/WebsiteBackend/sessions
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":BauSystem:BauSystem_Main", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.nms15)
|
||||
compileOnly(libs.worldedit15)
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.SideEffectSet;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Waterlogged;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class FlatteningWrapper15 implements FlatteningWrapper {
|
||||
|
||||
@Override
|
||||
public boolean isNoBook(ItemStack item) {
|
||||
return item.getType() != Material.WRITABLE_BOOK && item.getType() != Material.WRITTEN_BOOK;
|
||||
}
|
||||
|
||||
private static final Set<Material> unpushable = new HashSet<>(Arrays.asList(Material.BARRIER, Material.BEACON, Material.COMMAND_BLOCK, Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.ENCHANTING_TABLE, Material.END_GATEWAY, Material.END_PORTAL, Material.ENDER_CHEST, Material.GRINDSTONE, Material.JIGSAW, Material.JUKEBOX, Material.NETHER_PORTAL, Material.OBSIDIAN, Material.STRUCTURE_VOID, Material.BARREL, Material.BEEHIVE, Material.BEE_NEST, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CHEST, Material.DAYLIGHT_DETECTOR, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.LECTERN, Material.SMOKER, Material.TRAPPED_CHEST));
|
||||
|
||||
// TODO: FLOWER
|
||||
private static final Set<Material> breaking = new HashSet<>(Arrays.asList(Material.BAMBOO, Material.CACTUS, Material.CAKE, Material.CARVED_PUMPKIN, Material.CHORUS_FLOWER, Material.CHORUS_PLANT, Material.COBWEB, Material.COCOA, Material.DRAGON_EGG, Material.FIRE, Material.FLOWER_POT, Material.JACK_O_LANTERN, Material.LADDER, Material.LAVA, Material.LAVA, Material.LEVER, Material.LILY_PAD, Material.MELON, Material.NETHER_WART, Material.PUMPKIN, Material.COMPARATOR, Material.REDSTONE_WIRE, Material.REPEATER, Material.TORCH, Material.STRUCTURE_VOID, Material.SCAFFOLDING, Material.SEA_PICKLE, Material.SNOW, Material.SUGAR_CANE, Material.TORCH, Material.TRIPWIRE, Material.TRIPWIRE_HOOK, Material.TURTLE_EGG, Material.VINE, Material.WATER, Material.WHEAT));
|
||||
|
||||
@Override
|
||||
public boolean isUnpusheable(Material material) {
|
||||
if (unpushable.contains(material)) {
|
||||
return true;
|
||||
}
|
||||
String name = material.name();
|
||||
return name.contains("BANNER") || name.contains("SIGN");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBreakingOnPush(Material material) {
|
||||
if (breaking.contains(material)) {
|
||||
return true;
|
||||
}
|
||||
String name = material.name();
|
||||
return name.contains("BED") || name.contains("BUTTON") || name.contains("CARPET") || (name.contains("DOOR") && !name.contains("TRAPDOOR")) || name.contains("HEAD") || name.contains("LEAVES") || name.contains("MUSHROOM") || name.contains("PRESSURE_PLATE") || name.contains("SHULKER_BOX");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWorldEditCommand(String command) {
|
||||
if (command.startsWith("/")) {
|
||||
command = command.replaceFirst("/", "");
|
||||
}
|
||||
command = command.toLowerCase();
|
||||
return WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getCommandManager().containsCommand(command);
|
||||
}
|
||||
|
||||
private static final WorldEditPlugin WORLDEDIT_PLUGIN = Objects.requireNonNull((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"));
|
||||
private static final World BUKKITWORLD = new BukkitWorld(Bukkit.getWorlds().get(0));
|
||||
|
||||
@Override
|
||||
public void setSelection(Player p, Point minPoint, Point maxPoint) {
|
||||
WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, minPoint.toBlockVector3(), maxPoint.toBlockVector3()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard loadSchematic(File file) {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
Clipboard clipboard;
|
||||
try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) {
|
||||
clipboard = reader.read();
|
||||
} catch (NullPointerException | IOException e) {
|
||||
throw new SecurityException("Bausystem schematic not found", e);
|
||||
}
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSession paste(PasteBuilder pasteBuilder) {
|
||||
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) {
|
||||
Clipboard clipboard = pasteBuilder.getClipboard();
|
||||
|
||||
if (!pasteBuilder.getMappers().isEmpty()) {
|
||||
BlockVector3 minimum = clipboard.getRegion().getMinimumPoint();
|
||||
for (int x = 0; x < clipboard.getDimensions().getX(); x++) {
|
||||
for (int y = 0; y < clipboard.getDimensions().getY(); y++) {
|
||||
for (int z = 0; z < clipboard.getDimensions().getZ(); z++) {
|
||||
BlockVector3 pos = minimum.add(x, y, z);
|
||||
pasteBuilder.getMappers().forEach(mapper -> mapper.accept(clipboard, pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomicReference<BlockVector3> pastePoint = new AtomicReference<>();
|
||||
if (!pasteBuilder.getPredicates().isEmpty()) {
|
||||
e.setMask(new Mask() {
|
||||
@Override
|
||||
public boolean test(BlockVector3 blockVector3) {
|
||||
BaseBlock block = clipboard.getFullBlock(blockVector3.subtract(pastePoint.get()).add(clipboard.getRegion().getMinimumPoint()));
|
||||
String blockName = block.getBlockType().toString().toLowerCase();
|
||||
for (BiPredicate<BaseBlock, String> predicate : pasteBuilder.getPredicates()) {
|
||||
if (!predicate.test(block, blockName)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Mask copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ClipboardHolder ch = new ClipboardHolder(clipboard);
|
||||
BlockVector3 dimensions = clipboard.getDimensions();
|
||||
BlockVector3 v;
|
||||
BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
|
||||
if (pasteBuilder.getPastPoint() != null) {
|
||||
v = pasteBuilder.getPastPoint().toBlockVector3();
|
||||
if (pasteBuilder.isRotate()) {
|
||||
ch.setTransform(new AffineTransform().rotateY(180));
|
||||
v = v.add(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset.multiply(-1, 1, -1)).subtract(0, 0, 1);
|
||||
} else {
|
||||
v = v.subtract(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset);
|
||||
}
|
||||
} else {
|
||||
v = pasteBuilder.getMinPoint().toBlockVector3().subtract(offset);
|
||||
}
|
||||
pastePoint.set(v);
|
||||
|
||||
if (pasteBuilder.isReset()) {
|
||||
e.setBlocks(new CuboidRegion(pasteBuilder.getMinPoint().toBlockVector3(), pasteBuilder.getMaxPoint().toBlockVector3()), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock());
|
||||
if (pasteBuilder.getWaterLevel() != 0) {
|
||||
e.setBlocks(new CuboidRegion(pasteBuilder.getMinPoint().toBlockVector3(), pasteBuilder.getMaxPoint().toBlockVector3().withY(pasteBuilder.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock());
|
||||
}
|
||||
}
|
||||
e.setSideEffectApplier(SideEffectSet.none());
|
||||
Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(pasteBuilder.isIgnoreAir()).build());
|
||||
return e;
|
||||
} catch (WorldEditException e) {
|
||||
throw new SecurityException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard copy(Point minPoint, Point maxPoint, Point copyPoint) {
|
||||
BukkitWorld bukkitWorld = new BukkitWorld(Bukkit.getWorlds().get(0));
|
||||
CuboidRegion region = new CuboidRegion(bukkitWorld, minPoint.toBlockVector3(), maxPoint.toBlockVector3());
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(bukkitWorld, -1)) {
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(
|
||||
e, region, clipboard, region.getMinimumPoint()
|
||||
);
|
||||
|
||||
copy.setCopyingEntities(false);
|
||||
copy.setCopyingBiomes(false);
|
||||
|
||||
Operations.complete(copy);
|
||||
clipboard.setOrigin(copyPoint.toBlockVector3());
|
||||
return clipboard;
|
||||
} catch (WorldEditException e) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean backup(Point minPoint, Point maxPoint, File file) {
|
||||
Clipboard clipboard = copy(minPoint, maxPoint, minPoint);
|
||||
try (ClipboardWriter writer = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) {
|
||||
writer.write(clipboard);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inWater(org.bukkit.World world, Vector tntPosition) {
|
||||
Block block = world.getBlockAt(tntPosition.getBlockX(), tntPosition.getBlockY(), tntPosition.getBlockZ());
|
||||
if (block.getType() == Material.WATER)
|
||||
return true;
|
||||
|
||||
BlockData data = block.getBlockData();
|
||||
if (!(data instanceof Waterlogged))
|
||||
return false;
|
||||
|
||||
return ((Waterlogged) data).isWaterlogged();
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.features.util.NoClipCommand;
|
||||
import net.minecraft.server.v1_15_R1.*;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NMSWrapper15 implements NMSWrapper {
|
||||
|
||||
private static final Reflection.Field<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setInternalGameMode(Player player, GameMode gameMode) {
|
||||
playerGameMode.set(((CraftPlayer) player).getHandle().playerInteractManager, EnumGamemode.getById(gameMode.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSlotToItemStack(Player player, Object o) {
|
||||
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
|
||||
int index = packetPlayInSetCreativeSlot.b();
|
||||
if (index >= 36 && index <= 44) {
|
||||
index -= 36;
|
||||
} else if (index > 44) {
|
||||
index -= 5;
|
||||
} else if (index <= 8) {
|
||||
index = index - 8 + 36;
|
||||
}
|
||||
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.getItemStack()));
|
||||
if (index < 9) player.getInventory().setHeldItemSlot(index);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
private static final Reflection.Field<Integer> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, int.class, 0);
|
||||
|
||||
@Override
|
||||
public void setGameStateChangeReason(Object packet) {
|
||||
gameStateChangeReason.set(packet, 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerBuildAbilities(Player player) {
|
||||
((CraftPlayer) player).getHandle().abilities.mayBuild = true;
|
||||
((CraftPlayer) player).getHandle().abilities.canInstantlyBuild = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material pathMaterial() {
|
||||
return Material.GRASS_PATH;
|
||||
}
|
||||
|
||||
private static final int threshold = 2048;
|
||||
|
||||
@Override
|
||||
public boolean checkItemStack(ItemStack item) {
|
||||
net.minecraft.server.v1_15_R1.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
|
||||
NBTTagCompound tag = nmsItem.getTag();
|
||||
if (tag != null && tag.hasKey("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = tag.getCompound("BlockEntityTag");
|
||||
if (blockTag.hasKey("Items")) {
|
||||
return drillDown(blockTag.getList("Items", 10), 0, 0) > threshold;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int drillDown(NBTTagList items, int layer, int start) {
|
||||
if (layer > 2) return start + threshold;
|
||||
int invalid = start;
|
||||
for (NBTBase nbtBase : items) {
|
||||
if (!(nbtBase instanceof NBTTagCompound))
|
||||
continue;
|
||||
NBTTagCompound slot = (NBTTagCompound) nbtBase;
|
||||
if (slot.hasKey("tag")) {
|
||||
invalid += slot.getByte("Count");
|
||||
NBTTagCompound iTag = slot.getCompound("tag");
|
||||
if (iTag.hasKey("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = iTag.getCompound("BlockEntityTag");
|
||||
if (blockTag.hasKey("Items")) {
|
||||
invalid = drillDown(blockTag.getList("Items", 10), layer + 1, invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid > threshold)
|
||||
break;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
private final Class<?> explosionPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
private final Reflection.Field<Double> a = Reflection.getField(explosionPacket, double.class, 0);
|
||||
private final Reflection.Field<Double> b = Reflection.getField(explosionPacket, double.class, 1);
|
||||
private final Reflection.Field<Double> c = Reflection.getField(explosionPacket, double.class, 2);
|
||||
private final Reflection.Field<Float> d = Reflection.getField(explosionPacket, float.class, 0);
|
||||
private final Reflection.Field<List> e = Reflection.getField(explosionPacket, List.class, 0);
|
||||
|
||||
@Override
|
||||
public Object resetExplosionKnockback(Object packet) {
|
||||
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
|
||||
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), Vec3D.a);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class PlaceItemWrapper15 implements PlaceItemWrapper {
|
||||
|
||||
public PlaceItemWrapper15() {
|
||||
for (Material material : Material.values()) {
|
||||
if (!material.isBlock()) continue;
|
||||
if (material.isLegacy()) continue;
|
||||
|
||||
String nonWall = material.name().replace("_WALL_", "").replace("WALL_", "").replace("_WALL", "");
|
||||
try {
|
||||
Material nonWallMaterial = Material.valueOf(nonWall);
|
||||
if (nonWallMaterial != material && nonWallMaterial.isItem() && !nonWallMaterial.isBlock()) {
|
||||
BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(nonWallMaterial, material);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
ITEM_MATERIAL_TO_BLOCK_MATERIAL.put(Material.REDSTONE, Material.REDSTONE_WIRE);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.server.v1_15_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_15_R1.PacketPlayInFlying;
|
||||
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerMovementWrapper15 implements PlayerMovementWrapper {
|
||||
|
||||
@Override
|
||||
public void setPosition(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (Float.isNaN(packetPlayInFlying.a(Float.NaN))) {
|
||||
entityPlayer.e(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0));
|
||||
} else {
|
||||
entityPlayer.setLocation(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0), packetPlayInFlying.a(0F), packetPlayInFlying.b(0F));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToOut(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
Object packet = Reflection.newInstance(teleportPacket);
|
||||
teleportEntity.set(packet, player.getEntityId());
|
||||
teleportPosition.set(packet, packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0),
|
||||
Float.isNaN(packetPlayInFlying.a(Float.NaN)) ? player.getLocation().getYaw() : packetPlayInFlying.a(0.0F),
|
||||
Float.isNaN(packetPlayInFlying.b(Float.NaN)) ? player.getLocation().getPitch() : packetPlayInFlying.b(0.0F));
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
public class TickListener15 implements TickListener {
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.utils.bossbar.BossBarService;
|
||||
import de.steamwar.bausystem.utils.tps.TPSFreezeUtils;
|
||||
import de.steamwar.bausystem.utils.tps.TPSLimitUtils;
|
||||
import de.steamwar.core.TPSWarpUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class TickManager15 implements TickManager, Listener {
|
||||
|
||||
private static float currentTPSLimit = 20;
|
||||
private boolean currentlyStepping = false;
|
||||
private float currentLimit;
|
||||
private int stepsTotal;
|
||||
private int stepsLeft;
|
||||
|
||||
@Override
|
||||
public boolean canFreeze() {
|
||||
return TPSFreezeUtils.isCanFreeze();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTickRate(float tickRate) {
|
||||
if (currentlyStepping) {
|
||||
currentlyStepping = false;
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
BossBarService.instance.remove(player, Region.getGlobalRegion(), "TickStep");
|
||||
});
|
||||
}
|
||||
TPSWarpUtils.warp(tickRate);
|
||||
if (currentTPSLimit == 0 && tickRate != 0) {
|
||||
TPSFreezeUtils.unfreeze();
|
||||
}
|
||||
currentTPSLimit = tickRate;
|
||||
if (tickRate == 0) {
|
||||
TPSLimitUtils.unlimit();
|
||||
TPSFreezeUtils.freeze();
|
||||
} else if (tickRate < 20.0) {
|
||||
TPSLimitUtils.limit(tickRate);
|
||||
} else if (tickRate >= 20) {
|
||||
TPSLimitUtils.unlimit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFrozen() {
|
||||
return TPSFreezeUtils.frozen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFreeze(boolean freeze) {
|
||||
if (freeze) {
|
||||
setTickRate(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stepTicks(int ticks) {
|
||||
currentLimit = 0;
|
||||
setTickRate(20);
|
||||
stepsLeft = ticks;
|
||||
stepsTotal = ticks;
|
||||
currentlyStepping = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sprintTicks(int ticks) {
|
||||
currentLimit = currentTPSLimit;
|
||||
setTickRate(4000);
|
||||
stepsLeft = ticks;
|
||||
stepsTotal = ticks;
|
||||
currentlyStepping = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSprinting() {
|
||||
return currentlyStepping && currentTPSLimit > 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStepping() {
|
||||
return currentlyStepping && currentTPSLimit <= 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTickRate() {
|
||||
return currentTPSLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockTpsPacket(boolean block) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalTicks() {
|
||||
return stepsTotal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDoneTicks() {
|
||||
return stepsTotal - stepsLeft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingTicks() {
|
||||
return stepsLeft;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTickEnd(TickEndEvent event) {
|
||||
if (!currentlyStepping) return;
|
||||
stepsLeft--;
|
||||
if (stepsLeft <= 0) {
|
||||
setTickRate(currentLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils.tps;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.core.BountifulWrapper;
|
||||
import de.steamwar.core.ChatWrapper;
|
||||
import de.steamwar.core.Core;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@UtilityClass
|
||||
class PacketCache {
|
||||
|
||||
private static List<Object> packets = new ArrayList<>();
|
||||
private static Set<Entity> entities = new HashSet<>();
|
||||
private static BukkitTask task = null;
|
||||
|
||||
private static Class<?> vec3dClass = Reflection.getClass("net.minecraft.world.phys.Vec3");
|
||||
private static Reflection.Field<Object> zeroVec3d = (Reflection.Field<Object>) Reflection.getField(vec3dClass, vec3dClass, 0);
|
||||
private static Object ZERO_VEC3D = zeroVec3d.get(null);
|
||||
private static Class<?> velocityPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket");
|
||||
private static Reflection.Constructor velocityPacketConstructor = Reflection.getConstructor(velocityPacketClass, int.class, vec3dClass);
|
||||
|
||||
private static Class<?> teleportPacketClass = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket");
|
||||
private static Class<?> entityClass = Reflection.getClass("net.minecraft.world.entity.Entity");
|
||||
private static Reflection.Constructor teleportPacketConstructor = Reflection.getConstructor(teleportPacketClass, entityClass);
|
||||
|
||||
private static Class<?> craftEntityClass = Reflection.getClass("org.bukkit.craftbukkit.entity.CraftEntity");
|
||||
private static Reflection.Method getHandle = Reflection.getMethod(craftEntityClass, "getHandle");
|
||||
|
||||
private static Object noGravityDataWatcher = BountifulWrapper.impl.getDataWatcherObject(5, Boolean.class);
|
||||
private static Object fuseDataWatcher = BountifulWrapper.impl.getDataWatcherObject(8, Integer.class);
|
||||
|
||||
public void continuousSendCache() {
|
||||
if (task != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
createPackets();
|
||||
task = new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
_sendCache();
|
||||
}
|
||||
}.runTaskTimer(Core.getInstance(), 1, 1);
|
||||
}
|
||||
|
||||
public void sendCache() {
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
_sendCache();
|
||||
}
|
||||
|
||||
private void _sendCache() {
|
||||
createPackets();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
for (Object packet : packets) {
|
||||
TinyProtocol.instance.sendPacket(player, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
packets.clear();
|
||||
entities.clear();
|
||||
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void createPackets() {
|
||||
if (entities.stream().anyMatch(Entity::isDead)) {
|
||||
entities.clear();
|
||||
packets.clear();
|
||||
}
|
||||
List<Entity> entities = Bukkit.getWorlds().get(0).getEntities().stream()
|
||||
.filter(e -> !(e instanceof Player))
|
||||
.filter(e -> PacketCache.entities.add(e))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (Entity entity : entities) {
|
||||
packets.add(teleportPacketConstructor.invoke(getHandle.invoke(entity)));
|
||||
}
|
||||
for (Entity entity : entities) {
|
||||
packets.add(velocityPacketConstructor.invoke(entity.getEntityId(), ZERO_VEC3D));
|
||||
}
|
||||
for (Entity entity : entities) {
|
||||
packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), noGravityDataWatcher, true));
|
||||
}
|
||||
for (Entity entity : entities) {
|
||||
if (!(entity instanceof TNTPrimed)) continue;
|
||||
TNTPrimed tnt = (TNTPrimed) entity;
|
||||
int fuse = tnt.getFuseTicks();
|
||||
packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), fuseDataWatcher, fuse - (fuse % 5) + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils.tps;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
@UtilityClass
|
||||
public class TPSFreezeUtils {
|
||||
|
||||
private static Reflection.Field<Boolean> fieldAccessor;
|
||||
@Getter
|
||||
private static final boolean canFreeze;
|
||||
|
||||
private static final Reflection.Method getWorldHandle = Reflection.getTypedMethod(Reflection.getClass("org.bukkit.craftbukkit.CraftWorld"), "getHandle", null);
|
||||
|
||||
@Getter
|
||||
private static boolean frozen = false;
|
||||
|
||||
private static final World world = Bukkit.getWorlds().get(0);
|
||||
|
||||
static {
|
||||
Reflection.Field<Boolean> fieldAccessor;
|
||||
try {
|
||||
fieldAccessor = Reflection.getField(Reflection.getClass("net.minecraft.server.level.ServerLevel"), "freezed", boolean.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
fieldAccessor = null;
|
||||
}
|
||||
canFreeze = fieldAccessor != null;
|
||||
TPSFreezeUtils.fieldAccessor = fieldAccessor;
|
||||
}
|
||||
|
||||
public void freeze() {
|
||||
setFreeze(world, true);
|
||||
}
|
||||
|
||||
public void unfreeze() {
|
||||
setFreeze(world, false);
|
||||
}
|
||||
|
||||
public boolean frozen() {
|
||||
return canFreeze && frozen;
|
||||
}
|
||||
|
||||
private void setFreeze(World world, boolean state) {
|
||||
if (canFreeze) {
|
||||
fieldAccessor.set(getWorldHandle.invoke(world), state);
|
||||
if (state) {
|
||||
PacketCache.continuousSendCache();
|
||||
} else {
|
||||
PacketCache.clearCache();
|
||||
}
|
||||
frozen = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils.tps;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.bausystem.utils.PlayerMovementWrapper;
|
||||
import de.steamwar.core.Core;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@UtilityClass
|
||||
public class TPSLimitUtils {
|
||||
|
||||
private static long currentTime = System.nanoTime();
|
||||
private static BukkitTask tpsLimiter = null;
|
||||
private static Queue<Runnable> packetQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public void unlimit() {
|
||||
if (tpsLimiter != null) tpsLimiter.cancel();
|
||||
tpsLimiter = null;
|
||||
}
|
||||
|
||||
public void limit(double tps) {
|
||||
if (tpsLimiter != null) tpsLimiter.cancel();
|
||||
|
||||
double delay = 20 / tps;
|
||||
int loops = (int) Math.ceil(delay);
|
||||
long sleepDelay = (long) (50 * delay) / loops;
|
||||
|
||||
tpsLimiter = Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||
PacketCache.sendCache();
|
||||
for (int i = 0; i < loops; i++) {
|
||||
sleepUntilNextTick(sleepDelay);
|
||||
PacketCache.sendCache();
|
||||
while (true) {
|
||||
Runnable runnable = packetQueue.poll();
|
||||
if (runnable == null) break;
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
PacketCache.clearCache();
|
||||
}, 0, 1);
|
||||
}
|
||||
|
||||
private void sleepUntilNextTick(long neededDelta) {
|
||||
long lastTime = currentTime;
|
||||
currentTime = System.nanoTime();
|
||||
|
||||
long timeDelta = (currentTime - lastTime) / 1000000;
|
||||
if (neededDelta - timeDelta < 0) return;
|
||||
|
||||
try {
|
||||
Thread.sleep(neededDelta - timeDelta);
|
||||
currentTime = System.nanoTime();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static {
|
||||
long timeInterval = 50;
|
||||
final long[] lastTime = {System.currentTimeMillis()};
|
||||
final double[] tps = {20.0};
|
||||
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime > lastTime[0]) {
|
||||
tps[0] = (double)timeInterval / (double)(currentTime - lastTime[0]) * 20.0;
|
||||
}
|
||||
|
||||
lastTime[0] = currentTime;
|
||||
|
||||
Bukkit.getOnlinePlayers().forEach(player -> {
|
||||
SWUtils.sendToActionbar(player, String.valueOf((int) (tps[0] * 10.0) / 10.0));
|
||||
});
|
||||
}, timeInterval / 50L, timeInterval / 50L);
|
||||
}
|
||||
*/
|
||||
|
||||
private static final Class<?> position = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
|
||||
private static final Class<?> positionLook = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
|
||||
static {
|
||||
BiFunction<Player, Object, Object> positionSetter = (player, o) -> {
|
||||
if (tpsLimiter != null) {
|
||||
Object object = PlayerMovementWrapper.impl.convertToOut(player, o);
|
||||
packetQueue.add(() -> {
|
||||
PlayerMovementWrapper.impl.setPosition(player, o);
|
||||
Bukkit.getOnlinePlayers().forEach(p -> {
|
||||
if (p == player) return;
|
||||
TinyProtocol.instance.sendPacket(p, object);
|
||||
});
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return o;
|
||||
};
|
||||
TinyProtocol.instance.addFilter(position, positionSetter);
|
||||
TinyProtocol.instance.addFilter(positionLook, positionSetter);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":BauSystem:BauSystem_Main", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.nms18)
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.features.util.NoClipCommand;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
import net.minecraft.server.level.PlayerInteractManager;
|
||||
import net.minecraft.world.level.EnumGamemode;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NMSWrapper18 implements NMSWrapper {
|
||||
|
||||
private static final Reflection.Field<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setInternalGameMode(Player player, GameMode gameMode) {
|
||||
playerGameMode.set(((CraftPlayer) player).getHandle().d, EnumGamemode.a(gameMode.getValue()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSlotToItemStack(Player player, Object o) {
|
||||
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
|
||||
int index = packetPlayInSetCreativeSlot.b();
|
||||
if (index >= 36 && index <= 44) {
|
||||
index -= 36;
|
||||
} else if (index > 44) {
|
||||
index -= 5;
|
||||
} else if (index <= 8) {
|
||||
index = index - 8 + 36;
|
||||
}
|
||||
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
|
||||
if (index < 9) player.getInventory().setHeldItemSlot(index);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
private static final Reflection.Field<PacketPlayOutGameStateChange.a> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
|
||||
|
||||
@Override
|
||||
public void setGameStateChangeReason(Object packet) {
|
||||
gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerBuildAbilities(Player player) {
|
||||
((CraftPlayer) player).getHandle().fs().d = true;
|
||||
((CraftPlayer) player).getHandle().fs().e = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material pathMaterial() {
|
||||
return Material.DIRT_PATH;
|
||||
}
|
||||
|
||||
private static final int threshold = 2048;
|
||||
|
||||
@Override
|
||||
public boolean checkItemStack(ItemStack item) {
|
||||
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
|
||||
NBTTagCompound tag = nmsItem.t();
|
||||
if (tag != null && tag.e("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = tag.p("BlockEntityTag");
|
||||
if (blockTag.e("Items")) {
|
||||
return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int drillDown(NBTTagList items, int layer, int start) {
|
||||
if (layer > 2) return start + threshold;
|
||||
int invalid = start;
|
||||
for (NBTBase nbtBase : items) {
|
||||
if (!(nbtBase instanceof NBTTagCompound))
|
||||
continue;
|
||||
NBTTagCompound slot = (NBTTagCompound) nbtBase;
|
||||
if (slot.e("tag")) {
|
||||
invalid += slot.f("Count");
|
||||
NBTTagCompound iTag = slot.p("tag");
|
||||
if (iTag.e("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = iTag.p("BlockEntityTag");
|
||||
if (blockTag.e("Items")) {
|
||||
invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid > threshold)
|
||||
break;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
private final Class<?> explosionPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
private final Reflection.Field<Double> a = Reflection.getField(explosionPacket, double.class, 0);
|
||||
private final Reflection.Field<Double> b = Reflection.getField(explosionPacket, double.class, 1);
|
||||
private final Reflection.Field<Double> c = Reflection.getField(explosionPacket, double.class, 2);
|
||||
private final Reflection.Field<Float> d = Reflection.getField(explosionPacket, float.class, 0);
|
||||
private final Reflection.Field<List> e = Reflection.getField(explosionPacket, List.class, 0);
|
||||
|
||||
@Override
|
||||
public Object resetExplosionKnockback(Object packet) {
|
||||
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
|
||||
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.network.protocol.game.PacketPlayInFlying;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerMovementWrapper18 implements PlayerMovementWrapper {
|
||||
|
||||
@Override
|
||||
public void setPosition(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (packetPlayInFlying.h) {
|
||||
entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
|
||||
} else {
|
||||
entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToOut(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
Object packet = Reflection.newInstance(teleportPacket);
|
||||
teleportEntity.set(packet, player.getEntityId());
|
||||
teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c,
|
||||
packetPlayInFlying.h ? player.getLocation().getYaw() : packetPlayInFlying.d,
|
||||
packetPlayInFlying.h ? player.getLocation().getPitch() : packetPlayInFlying.e);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":BauSystem:BauSystem_Main", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.paperapi)
|
||||
|
||||
compileOnly(libs.nms19)
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.features.util.NoClipCommand;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
import net.minecraft.server.level.PlayerInteractManager;
|
||||
import net.minecraft.world.level.EnumGamemode;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NMSWrapper19 implements NMSWrapper {
|
||||
|
||||
private static final Reflection.Field<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setInternalGameMode(Player player, GameMode gameMode) {
|
||||
playerGameMode.set(((CraftPlayer) player).getHandle().d, EnumGamemode.a(gameMode.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSlotToItemStack(Player player, Object o) {
|
||||
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
|
||||
int index = packetPlayInSetCreativeSlot.b();
|
||||
if (index >= 36 && index <= 44) {
|
||||
index -= 36;
|
||||
} else if (index > 44) {
|
||||
index -= 5;
|
||||
} else if (index <= 8) {
|
||||
index = index - 8 + 36;
|
||||
}
|
||||
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
|
||||
if (index < 9) player.getInventory().setHeldItemSlot(index);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
private static final Reflection.Field<PacketPlayOutGameStateChange.a> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
|
||||
|
||||
@Override
|
||||
public void setGameStateChangeReason(Object packet) {
|
||||
gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerBuildAbilities(Player player) {
|
||||
((CraftPlayer) player).getHandle().fF().d = true;
|
||||
((CraftPlayer) player).getHandle().fF().e = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material pathMaterial() {
|
||||
return Material.DIRT_PATH;
|
||||
}
|
||||
|
||||
private static final int threshold = 2048;
|
||||
|
||||
@Override
|
||||
public boolean checkItemStack(ItemStack item) {
|
||||
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
|
||||
NBTTagCompound tag = nmsItem.v();
|
||||
if (tag != null && tag.e("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = tag.p("BlockEntityTag");
|
||||
if (blockTag.e("Items")) {
|
||||
return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int drillDown(NBTTagList items, int layer, int start) {
|
||||
if (layer > 2) return start + threshold;
|
||||
int invalid = start;
|
||||
for (NBTBase nbtBase : items) {
|
||||
if (!(nbtBase instanceof NBTTagCompound))
|
||||
continue;
|
||||
NBTTagCompound slot = (NBTTagCompound) nbtBase;
|
||||
if (slot.e("tag")) {
|
||||
invalid += slot.f("Count");
|
||||
NBTTagCompound iTag = slot.p("tag");
|
||||
if (iTag.e("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = iTag.p("BlockEntityTag");
|
||||
if (blockTag.e("Items")) {
|
||||
invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid > threshold)
|
||||
break;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
private final Class<?> explosionPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
private final Reflection.Field<Double> a = Reflection.getField(explosionPacket, double.class, 0);
|
||||
private final Reflection.Field<Double> b = Reflection.getField(explosionPacket, double.class, 1);
|
||||
private final Reflection.Field<Double> c = Reflection.getField(explosionPacket, double.class, 2);
|
||||
private final Reflection.Field<Float> d = Reflection.getField(explosionPacket, float.class, 0);
|
||||
private final Reflection.Field<List> e = Reflection.getField(explosionPacket, List.class, 0);
|
||||
|
||||
@Override
|
||||
public Object resetExplosionKnockback(Object packet) {
|
||||
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
|
||||
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.network.protocol.game.PacketPlayInFlying;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerMovementWrapper19 implements PlayerMovementWrapper {
|
||||
|
||||
@Override
|
||||
public void setPosition(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (packetPlayInFlying.h) {
|
||||
entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
|
||||
} else {
|
||||
entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToOut(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
Object packet = Reflection.newInstance(teleportPacket);
|
||||
teleportEntity.set(packet, player.getEntityId());
|
||||
teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c,
|
||||
packetPlayInFlying.h ? player.getLocation().getYaw() : packetPlayInFlying.d,
|
||||
packetPlayInFlying.h ? player.getLocation().getPitch() : packetPlayInFlying.e);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import com.destroystokyo.paper.event.server.ServerTickEndEvent;
|
||||
import com.destroystokyo.paper.event.server.ServerTickStartEvent;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class TickListener19 implements TickListener, Listener {
|
||||
|
||||
private boolean tickStartRan = false;
|
||||
|
||||
public TickListener19() {
|
||||
Bukkit.getPluginManager().registerEvents(this, BauSystem.getInstance());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerTickStart(ServerTickStartEvent event) {
|
||||
if (TickManager.impl.isFrozen()) return;
|
||||
Bukkit.getPluginManager().callEvent(new TickStartEvent());
|
||||
tickStartRan = true;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onServerTickEnd(ServerTickEndEvent event) {
|
||||
if (!tickStartRan) return;
|
||||
Bukkit.getPluginManager().callEvent(new TickEndEvent());
|
||||
tickStartRan = false;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":BauSystem:BauSystem_Main", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
|
||||
compileOnly(libs.nms20)
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.features.util.NoClipCommand;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutExplosion;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange;
|
||||
import net.minecraft.server.level.PlayerInteractManager;
|
||||
import net.minecraft.world.level.EnumGamemode;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NMSWrapper20 implements NMSWrapper {
|
||||
|
||||
private static final Reflection.Field<EnumGamemode> playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setInternalGameMode(Player player, GameMode gameMode) {
|
||||
playerGameMode.set(((CraftPlayer) player).getHandle().e, EnumGamemode.a(gameMode.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSlotToItemStack(Player player, Object o) {
|
||||
PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
|
||||
int index = packetPlayInSetCreativeSlot.a();
|
||||
if (index >= 36 && index <= 44) {
|
||||
index -= 36;
|
||||
} else if (index > 44) {
|
||||
index -= 5;
|
||||
} else if (index <= 8) {
|
||||
index = index - 8 + 36;
|
||||
}
|
||||
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
|
||||
if (index < 9) player.getInventory().setHeldItemSlot(index);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
private static final Reflection.Field<PacketPlayOutGameStateChange.a> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
|
||||
|
||||
@Override
|
||||
public void setGameStateChangeReason(Object packet) {
|
||||
gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerBuildAbilities(Player player) {
|
||||
((CraftPlayer) player).getHandle().fO().d = true;
|
||||
((CraftPlayer) player).getHandle().fO().e = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material pathMaterial() {
|
||||
return Material.DIRT_PATH;
|
||||
}
|
||||
|
||||
private static final int threshold = 2048;
|
||||
|
||||
@Override
|
||||
public boolean checkItemStack(ItemStack item) {
|
||||
net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
|
||||
NBTTagCompound tag = nmsItem.v();
|
||||
if (tag != null && tag.e("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = tag.p("BlockEntityTag");
|
||||
if (blockTag.e("Items")) {
|
||||
return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int drillDown(NBTTagList items, int layer, int start) {
|
||||
if (layer > 2) return start + threshold;
|
||||
int invalid = start;
|
||||
for (NBTBase nbtBase : items) {
|
||||
if (!(nbtBase instanceof NBTTagCompound))
|
||||
continue;
|
||||
NBTTagCompound slot = (NBTTagCompound) nbtBase;
|
||||
if (slot.e("tag")) {
|
||||
invalid += slot.f("Count");
|
||||
NBTTagCompound iTag = slot.p("tag");
|
||||
if (iTag.e("BlockEntityTag")) {
|
||||
NBTTagCompound blockTag = iTag.p("BlockEntityTag");
|
||||
if (blockTag.e("Items")) {
|
||||
invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalid > threshold)
|
||||
break;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
private final Class<?> explosionPacket = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket");
|
||||
private final Reflection.Field<Double> a = Reflection.getField(explosionPacket, double.class, 0);
|
||||
private final Reflection.Field<Double> b = Reflection.getField(explosionPacket, double.class, 1);
|
||||
private final Reflection.Field<Double> c = Reflection.getField(explosionPacket, double.class, 2);
|
||||
private final Reflection.Field<Float> d = Reflection.getField(explosionPacket, float.class, 0);
|
||||
private final Reflection.Field<List> e = Reflection.getField(explosionPacket, List.class, 0);
|
||||
|
||||
@Override
|
||||
public Object resetExplosionKnockback(Object packet) {
|
||||
PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
|
||||
return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
public class PlaceItemWrapper20 implements PlaceItemWrapper {
|
||||
|
||||
public PlaceItemWrapper20() {
|
||||
for (Material material : Material.values()) {
|
||||
if (!material.isBlock()) continue;
|
||||
if (material.isLegacy()) continue;
|
||||
BlockData blockData = material.createBlockData();
|
||||
Material placementMaterial = blockData.getPlacementMaterial();
|
||||
if (material == placementMaterial) continue;
|
||||
if (placementMaterial == Material.AIR) continue;
|
||||
if (placementMaterial.isItem() && !placementMaterial.isBlock()) {
|
||||
ITEM_MATERIAL_TO_BLOCK_MATERIAL.put(placementMaterial, material);
|
||||
}
|
||||
if (material.name().contains("WALL")) {
|
||||
BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(placementMaterial, material);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import net.minecraft.network.protocol.game.PacketPlayInFlying;
|
||||
import net.minecraft.server.level.EntityPlayer;
|
||||
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerMovementWrapper20 implements PlayerMovementWrapper {
|
||||
|
||||
@Override
|
||||
public void setPosition(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (packetPlayInFlying.h) {
|
||||
entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
|
||||
} else {
|
||||
entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToOut(Player player, Object object) {
|
||||
PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
|
||||
Object packet = Reflection.newInstance(teleportPacket);
|
||||
teleportEntity.set(packet, player.getEntityId());
|
||||
teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c,
|
||||
packetPlayInFlying.h ? player.getLocation().getYaw() : packetPlayInFlying.d,
|
||||
packetPlayInFlying.h ? player.getLocation().getPitch() : packetPlayInFlying.e);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":BauSystem:BauSystem_Main", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.paperapi21)
|
||||
|
||||
compileOnly(libs.nms21)
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.features.util.NoClipCommand;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.datacomponent.item.ItemContainerContents;
|
||||
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundExplodePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.level.ServerPlayerGameMode;
|
||||
import net.minecraft.world.entity.player.Abilities;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class NMSWrapper21 implements NMSWrapper {
|
||||
|
||||
private static final Reflection.Field<ServerPlayerGameMode> playerInteractManager = Reflection.getField(ServerPlayer.class, null, ServerPlayerGameMode.class);
|
||||
private static final Reflection.Field<GameType> playerGameMode = Reflection.getField(ServerPlayerGameMode.class, GameType.class, 0);
|
||||
|
||||
@Override
|
||||
public void setInternalGameMode(Player player, GameMode gameMode) {
|
||||
playerGameMode.set(playerInteractManager.get(((CraftPlayer) player).getHandle()), GameType.byId(gameMode.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSlotToItemStack(Player player, Object o) {
|
||||
ClientboundContainerSetSlotPacket packetPlayInSetCreativeSlot = (ClientboundContainerSetSlotPacket) o;
|
||||
int index = packetPlayInSetCreativeSlot.getSlot();
|
||||
if (index >= 36 && index <= 44) {
|
||||
index -= 36;
|
||||
} else if (index > 44) {
|
||||
index -= 5;
|
||||
} else if (index <= 8) {
|
||||
index = index - 8 + 36;
|
||||
}
|
||||
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.getItem()));
|
||||
if (index < 9) player.getInventory().setHeldItemSlot(index);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
private static final Reflection.Field<ClientboundGameEventPacket.Type> gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, ClientboundGameEventPacket.Type.class, 14);
|
||||
|
||||
@Override
|
||||
public void setGameStateChangeReason(Object packet) {
|
||||
gameStateChangeReason.set(packet, ClientboundGameEventPacket.CHANGE_GAME_MODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerBuildAbilities(Player player) {
|
||||
Abilities abilities = (((CraftPlayer) player).getHandle()).getAbilities();
|
||||
abilities.mayBuild = true;
|
||||
abilities.mayfly = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material pathMaterial() {
|
||||
return Material.DIRT_PATH;
|
||||
}
|
||||
|
||||
private static final int threshold = 2048;
|
||||
|
||||
@Override
|
||||
public boolean checkItemStack(ItemStack item) {
|
||||
ItemContainerContents data = item.getData(DataComponentTypes.CONTAINER);
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drillDown(data.contents(), 0, 0) > threshold;
|
||||
}
|
||||
|
||||
private int drillDown(List<ItemStack> items, int layer, int start) {
|
||||
if (layer > 2) return start + threshold;
|
||||
int invalid = start;
|
||||
for (int i = start; i < items.size(); i++) {
|
||||
ItemStack item = items.get(i);
|
||||
if (item.isEmpty()) continue;
|
||||
|
||||
invalid += item.getAmount();
|
||||
|
||||
ItemContainerContents data = item.getData(DataComponentTypes.CONTAINER);
|
||||
if (data == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<ItemStack> subItems = data.contents();
|
||||
if (subItems.size() > 1) {
|
||||
invalid = drillDown(subItems, layer + 1, invalid);
|
||||
}
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resetExplosionKnockback(Object packet) {
|
||||
ClientboundExplodePacket explosion = (ClientboundExplodePacket) packet;
|
||||
|
||||
return new ClientboundExplodePacket(
|
||||
explosion.center(),
|
||||
Optional.empty(),
|
||||
explosion.explosionParticle(),
|
||||
explosion.explosionSound()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class PlayerMovementWrapper21 implements PlayerMovementWrapper {
|
||||
|
||||
@Override
|
||||
public void setPosition(Player player, Object object) {
|
||||
ServerboundMovePlayerPacket packetPlayInFlying = ((ServerboundMovePlayerPacket) object);
|
||||
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (packetPlayInFlying.hasPos) {
|
||||
serverPlayer.setPosRaw(packetPlayInFlying.x, packetPlayInFlying.y, packetPlayInFlying.z);
|
||||
}
|
||||
if (packetPlayInFlying.hasRot) {
|
||||
serverPlayer.setXRot(packetPlayInFlying.xRot);
|
||||
serverPlayer.setYRot(packetPlayInFlying.yRot);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertToOut(Player player, Object object) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import net.minecraft.network.protocol.game.ClientboundTickingStatePacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTickRateManager;
|
||||
import net.minecraft.world.TickRateManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TickManager21 implements TickManager {
|
||||
private static final ServerTickRateManager manager = MinecraftServer.getServer().tickRateManager();
|
||||
private static final Reflection.Field<Integer> frozenTicksToRun = Reflection.getField(TickRateManager.class, int.class, 0);
|
||||
private static final Reflection.Field<Long> remainingSprintTicks = Reflection.getField(ServerTickRateManager.class, long.class, 0);
|
||||
|
||||
private boolean blockTpsPacket = true;
|
||||
private int totalSteps;
|
||||
|
||||
public TickManager21() {
|
||||
TinyProtocol.instance.addFilter(ClientboundTickingStatePacket.class, this::blockPacket);
|
||||
}
|
||||
|
||||
private Object blockPacket(Player player, Object packet) {
|
||||
if (blockTpsPacket) {
|
||||
return new ClientboundTickingStatePacket(20, manager.isFrozen());
|
||||
} else {
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFreeze() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockTpsPacket(boolean block) {
|
||||
blockTpsPacket = block;
|
||||
if (blockTpsPacket) {
|
||||
ClientboundTickingStatePacket packet = new ClientboundTickingStatePacket(20, manager.isFrozen());
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
} else {
|
||||
ClientboundTickingStatePacket packet = new ClientboundTickingStatePacket(manager.tickrate(), manager.isFrozen());
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTickRate(float tickRate) {
|
||||
if (isFrozen()) {
|
||||
setFreeze(false);
|
||||
}
|
||||
manager.setTickRate(tickRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFrozen() {
|
||||
return manager.isFrozen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFreeze(boolean freeze) {
|
||||
manager.setFrozen(freeze);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stepTicks(int ticks) {
|
||||
if (manager.isSprinting()) {
|
||||
manager.stopSprinting();
|
||||
} else if (manager.isSteppingForward()) {
|
||||
manager.stopStepping();
|
||||
}
|
||||
this.totalSteps = ticks;
|
||||
manager.setFrozen(true);
|
||||
manager.stepGameIfPaused(ticks);
|
||||
manager.setFrozen(false);
|
||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), (bukkitTask) -> {
|
||||
if (manager.isSteppingForward()) return;
|
||||
manager.setFrozen(true);
|
||||
bukkitTask.cancel();
|
||||
}, 1, 1);
|
||||
manager.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sprintTicks(int ticks) {
|
||||
if (manager.isSteppingForward()) {
|
||||
manager.stopStepping();
|
||||
} else if (manager.isSprinting()) {
|
||||
manager.stopSprinting();
|
||||
}
|
||||
this.totalSteps = ticks;
|
||||
manager.requestGameToSprint(ticks, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSprinting() {
|
||||
return manager.isSprinting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStepping() {
|
||||
return manager.isSteppingForward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTickRate() {
|
||||
return manager.tickrate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingTicks() {
|
||||
if (isSprinting()) {
|
||||
return remainingSprintTicks.get(manager);
|
||||
} else {
|
||||
return frozenTicksToRun.get(manager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDoneTicks() {
|
||||
return totalSteps - getRemainingTicks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalTicks() {
|
||||
return totalSteps;
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,8 @@ tasks.compileJava {
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -35,10 +35,12 @@ dependencies {
|
||||
annotationProcessor(libs.classindex)
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.axiom)
|
||||
compileOnly(libs.authlib)
|
||||
|
||||
compileOnly(libs.paperapi21)
|
||||
compileOnly(libs.nms21)
|
||||
|
||||
compileOnly(libs.fawe18)
|
||||
|
||||
implementation(libs.luaj)
|
||||
|
||||
@@ -34,11 +34,11 @@ import de.steamwar.bausystem.features.world.BauScoreboard;
|
||||
import de.steamwar.bausystem.linkage.BauGuiItem;
|
||||
import de.steamwar.bausystem.region.RegionSystem;
|
||||
import de.steamwar.bausystem.utils.ScoreboardElement;
|
||||
import de.steamwar.bausystem.utils.TickListener;
|
||||
import de.steamwar.bausystem.utils.TickManager;
|
||||
import de.steamwar.bausystem.worlddata.WorldData;
|
||||
import de.steamwar.command.AbstractValidator;
|
||||
import de.steamwar.command.SWCommandUtils;
|
||||
import de.steamwar.core.CRIUSleepEvent;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.WorldEditRendererCUIEditor;
|
||||
import de.steamwar.core.WorldIdentifier;
|
||||
@@ -51,6 +51,8 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameRule;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
@@ -63,7 +65,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class BauSystem extends JavaPlugin {
|
||||
public class BauSystem extends JavaPlugin implements Listener {
|
||||
|
||||
// This should be treated as final!
|
||||
public static Message MESSAGE;
|
||||
@@ -124,8 +126,6 @@ public class BauSystem extends JavaPlugin {
|
||||
return;
|
||||
}
|
||||
|
||||
TickListener.impl.init();
|
||||
|
||||
TraceManager.instance.init();
|
||||
TraceRecorder.instance.init();
|
||||
|
||||
@@ -137,10 +137,16 @@ public class BauSystem extends JavaPlugin {
|
||||
WorldIdentifier.set("bau/" + Core.getVersion() + "/" + identifier);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCRIUSleep(CRIUSleepEvent event) {
|
||||
RegionSystem.INSTANCE.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
linker.unlink();
|
||||
WorldData.write();
|
||||
RegionSystem.INSTANCE.save();
|
||||
Config.getInstance().saveAll();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public class BauInfoBauGuiItem extends BauGuiItem {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
List<String> stringList = new ArrayList<>();
|
||||
for (Flag flag : Flag.getFlags()) {
|
||||
if (flag == Flag.CHANGED) continue;
|
||||
if (!region.getRegionData().has(flag).isApplicable()) continue;
|
||||
FlagOptional<?> value = region.getRegionData().get(flag);
|
||||
if (value.isPresent()) {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.dev;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Linked
|
||||
public class CreateKitCommand extends SWCommand {
|
||||
|
||||
public CreateKitCommand() {
|
||||
super("createkit");
|
||||
if (!BauSystem.DEV_SERVER) unregister();
|
||||
}
|
||||
|
||||
@Register
|
||||
public void onCommand(Player player, String name) {
|
||||
YamlConfiguration yaml = new YamlConfiguration();
|
||||
|
||||
yaml.set("Items", player.getInventory().getContents());
|
||||
yaml.set("Armor", player.getInventory().getArmorContents());
|
||||
yaml.set("Effects", player.getActivePotionEffects());
|
||||
yaml.set("LeaderAllowed", true);
|
||||
yaml.set("MemberAllowed", true);
|
||||
yaml.set("EnterStage", 0);
|
||||
yaml.set("TNT", true);
|
||||
|
||||
YamlConfiguration kits = new YamlConfiguration();
|
||||
|
||||
kits.set("Kits." + name, yaml);
|
||||
|
||||
try {
|
||||
kits.save(new File("new.kits.yaml"));
|
||||
|
||||
player.sendMessage("Kit created!");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -19,7 +19,6 @@
|
||||
|
||||
package de.steamwar.bausystem.features.observer;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.core.SWPlayer;
|
||||
import org.bukkit.Location;
|
||||
@@ -29,8 +28,9 @@ import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Observer;
|
||||
import org.bukkit.block.data.type.*;
|
||||
import org.bukkit.block.data.type.Observer;
|
||||
import org.bukkit.craftbukkit.block.impl.CraftPoweredRail;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
@@ -171,7 +171,6 @@ public class ObserverTracer implements SWPlayer.Component {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Class<?> craftPoweredRail = Reflection.getClass("org.bukkit.craftbukkit.block.impl.CraftPoweredRail");
|
||||
private boolean checkAllowed(Block block, BlockData blockData) {
|
||||
if (checkMaterial(block)) return true;
|
||||
if (block.getType() == Material.BELL) {
|
||||
@@ -180,7 +179,7 @@ public class ObserverTracer implements SWPlayer.Component {
|
||||
|
||||
return blockData instanceof Door
|
||||
|| blockData instanceof Gate
|
||||
|| craftPoweredRail.isInstance(blockData)
|
||||
|| blockData instanceof CraftPoweredRail
|
||||
|| blockData instanceof TrapDoor
|
||||
|| blockData instanceof GlassPane;
|
||||
}
|
||||
|
||||
+2
-2
@@ -63,11 +63,11 @@ public class ColorCommand extends SWCommand {
|
||||
}
|
||||
region.getRegionData().set(Flag.COLOR, color);
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(PasteBuilder.ClipboardProvider.EMPTY)
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile()))
|
||||
.ignoreAir(true)
|
||||
.onlyColors(true)
|
||||
.color(color);
|
||||
region.getArea().reset(p.getLocation(), pasteBuilder, false);
|
||||
region.getArea().reset(pasteBuilder, false);
|
||||
RegionUtils.message(region, "REGION_REGION_COLORED");
|
||||
RegionUtils.message(region, "REGION_REGION_COLORED_FAILED");
|
||||
} catch (SecurityException e) {
|
||||
|
||||
@@ -56,7 +56,6 @@ public class FireListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.FIRE).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.FIRE).isWithDefault(FireMode.DENY)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.FIRE.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.FIRE).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
+10
-1
@@ -46,6 +46,16 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
||||
@Linked
|
||||
public class FreezeListener implements Listener, ScoreboardElement {
|
||||
|
||||
@EventHandler
|
||||
public void onBlockExplode(BlockExplodeEvent e) {
|
||||
if (Region.getRegion(e.getBlock().getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return;
|
||||
e.setCancelled(true);
|
||||
BlockState state = e.getBlock().getState();
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
state.update(true, false);
|
||||
}, 1L);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEntitySpawn(EntitySpawnEvent e) {
|
||||
if (Region.getRegion(e.getLocation()).getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return;
|
||||
@@ -235,7 +245,6 @@ public class FreezeListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.FREEZE).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.FREEZE).isWithDefault(FreezeMode.INACTIVE)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.FREEZE.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.FREEZE).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ public class ItemsListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.ITEMS).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.ITEMS).isWithDefault(ItemMode.INACTIVE)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.ITEMS.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.ITEMS).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
-1
@@ -54,7 +54,6 @@ public class NoGravityListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.NO_GRAVITY).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.NO_GRAVITY).isWithDefault(NoGravityMode.INACTIVE)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.NO_GRAVITY.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.NO_GRAVITY).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
-1
@@ -70,7 +70,6 @@ public class ProtectListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.PROTECT).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.PROTECT).isWithDefault(ProtectMode.INACTIVE)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.PROTECT.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.PROTECT).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
+26
-9
@@ -30,7 +30,6 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.util.SelectCommand;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.RegionHistory;
|
||||
import de.steamwar.bausystem.region.RegionUtils;
|
||||
import de.steamwar.bausystem.region.flags.Flag;
|
||||
import de.steamwar.bausystem.shared.Pair;
|
||||
@@ -72,10 +71,7 @@ public class RegionCommand extends SWCommand {
|
||||
@Register(value = "undo", description = "REGION_REGION_HELP_UNDO")
|
||||
public void undoCommand(@Validator Player p) {
|
||||
Region region = Region.getRegion(p.getLocation());
|
||||
if (region.getHistory() == RegionHistory.EMPTY) {
|
||||
BauSystem.MESSAGE.send("REGION_REGION_NO_REGION", p);
|
||||
return;
|
||||
}
|
||||
if (checkGlobalRegion(region, p)) return;
|
||||
|
||||
if (region.getHistory().undo()) {
|
||||
RegionUtils.message(region, "REGION_REGION_UNDID");
|
||||
@@ -87,8 +83,7 @@ public class RegionCommand extends SWCommand {
|
||||
@Register(value = "redo", description = "REGION_REGION_HELP_REDO")
|
||||
public void redoCommand(@Validator Player p) {
|
||||
Region region = Region.getRegion(p.getLocation());
|
||||
if (region.getHistory() == RegionHistory.EMPTY) {
|
||||
BauSystem.MESSAGE.send("REGION_REGION_NO_REGION", p);
|
||||
if (checkGlobalRegion(region, p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,10 +100,32 @@ public class RegionCommand extends SWCommand {
|
||||
if(checkGlobalRegion(region, p)) return;
|
||||
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(PasteBuilder.ClipboardProvider.EMPTY)
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile()))
|
||||
.ignoreAir(true)
|
||||
.color(region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
region.getArea().reset(p.getLocation(), pasteBuilder, false);
|
||||
region.getArea().reset(pasteBuilder, false);
|
||||
RegionUtils.message(region, "REGION_REGION_RESTORED");
|
||||
} catch (SecurityException e) {
|
||||
BauSystem.MESSAGE.send("REGION_REGION_FAILED_RESTORE", p);
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed restore", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Register(value = "restore", description = "REGION_REGION_HELP_RESTORE_SCHEMATIC")
|
||||
public void schematicRestoreCommand(@Validator Player p, SchematicNode node) {
|
||||
Region region = Region.getRegion(p.getLocation());
|
||||
if (checkGlobalRegion(region, p)) return;
|
||||
|
||||
if(node.isDir()) {
|
||||
BauSystem.MESSAGE.send("ONLY_SCHEMS", p);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node))
|
||||
.ignoreAir(true)
|
||||
.color(region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
region.getArea().reset(pasteBuilder, false);
|
||||
RegionUtils.message(region, "REGION_REGION_RESTORED");
|
||||
} catch (SecurityException e) {
|
||||
BauSystem.MESSAGE.send("REGION_REGION_FAILED_RESTORE", p);
|
||||
|
||||
+34
-2
@@ -29,6 +29,9 @@ import de.steamwar.bausystem.utils.PasteBuilder;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import de.steamwar.sql.Punishment;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@@ -49,9 +52,9 @@ public class ResetCommand extends SWCommand {
|
||||
Region region = regionCheck(p);
|
||||
if (region == null) return;
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(PasteBuilder.ClipboardProvider.EMPTY)
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.FileProvider(region.getArea().getResetFile()))
|
||||
.color(region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
region.getArea().reset(p.getLocation(), pasteBuilder, false);
|
||||
region.getArea().reset(pasteBuilder, false);
|
||||
region.getRegionData().clear();
|
||||
RegionUtils.message(region, "REGION_RESET_RESETED");
|
||||
} catch (SecurityException e) {
|
||||
@@ -60,6 +63,35 @@ public class ResetCommand extends SWCommand {
|
||||
}
|
||||
}
|
||||
|
||||
@Register(description = "REGION_RESET_HELP_SCHEMATIC")
|
||||
public void schematicResetCommand(@Validator Player p, SchematicNode node) {
|
||||
Region region = regionCheck(p);
|
||||
if (region == null) return;
|
||||
|
||||
if (!p.getUniqueId().equals(bauServer.getOwner())) {
|
||||
if (Punishment.isPunished(SteamwarUser.get(bauServer.getOwner()), Punishment.PunishmentType.NoSchemReceiving, punishment -> BauSystem.MESSAGE.send("REGION_TB_NO_SCHEMRECEIVING", p, punishment.getEndTime()))) {
|
||||
return;
|
||||
}
|
||||
if (Punishment.isPunished(SteamwarUser.get(p.getUniqueId()), Punishment.PunishmentType.NoSchemSharing, punishment -> BauSystem.MESSAGE.send("REGION_TB_NO_SCHEMSHARING", p, punishment.getEndTime()))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.isDir()) {
|
||||
BauSystem.MESSAGE.send("ONLY_SCHEMS", p);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(new PasteBuilder.SchematicProvider(node))
|
||||
.color(region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
region.getArea().reset(pasteBuilder, true);
|
||||
RegionUtils.message(region, "REGION_RESET_RESETED");
|
||||
} catch (SecurityException e) {
|
||||
BauSystem.MESSAGE.send("REGION_RESET_ERROR", p);
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed reset", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Region regionCheck(Player player) {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
if (region == RegionSystem.INSTANCE.getGlobalRegion()) {
|
||||
|
||||
+1
-42
@@ -21,16 +21,13 @@ package de.steamwar.bausystem.features.region;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.RegionSystem;
|
||||
import de.steamwar.bausystem.region.RegionUtils;
|
||||
import de.steamwar.bausystem.region.flags.Flag;
|
||||
import de.steamwar.bausystem.region.flags.TNTMode;
|
||||
import de.steamwar.bausystem.utils.ScoreboardElement;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.TNTPrimed;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@@ -38,26 +35,12 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@Linked
|
||||
public class TNTListener implements Listener, ScoreboardElement {
|
||||
|
||||
private static final NamespacedKey SPAWN_REGION_ID = Objects.requireNonNull(NamespacedKey.fromString("spawn_region_id", BauSystem.getInstance()));
|
||||
|
||||
@EventHandler
|
||||
public void onEntitySpawn(EntitySpawnEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof TNTPrimed)) return;
|
||||
Region region = Region.getRegion(entity.getLocation());
|
||||
entity.getPersistentDataContainer().set(SPAWN_REGION_ID, PersistentDataType.STRING, region.getID().toString());
|
||||
}
|
||||
|
||||
private void explode(List<Block> blockList, boolean destroy) {
|
||||
blockList.removeIf(block -> {
|
||||
Region region = Region.getRegion(block.getLocation());
|
||||
@@ -84,30 +67,7 @@ public class TNTListener implements Listener, ScoreboardElement {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onExplode(EntityExplodeEvent event) {
|
||||
if (!(event.getEntity() instanceof TNTPrimed)) {
|
||||
event.blockList().clear();
|
||||
return;
|
||||
}
|
||||
|
||||
Entity entity = event.getEntity();
|
||||
Region currentRegion = Region.getRegion(entity.getLocation());
|
||||
String spawningRegionIdString = entity.getPersistentDataContainer().get(SPAWN_REGION_ID, PersistentDataType.STRING);
|
||||
UUID spawningRegionId = spawningRegionIdString == null ? null : UUID.fromString(spawningRegionIdString);
|
||||
|
||||
// TNT Only created block damage in the Region it spawned in or in a connected special region!
|
||||
if (!currentRegion.getID().equals(spawningRegionId)) {
|
||||
if (!currentRegion.getType().isSpecial()) {
|
||||
event.blockList().clear();
|
||||
return;
|
||||
}
|
||||
if (RegionSystem.INSTANCE.getConnectedRegions(currentRegion)
|
||||
.noneMatch(region -> region.getID().equals(spawningRegionId))) {
|
||||
event.blockList().clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
explode(event.blockList(), true);
|
||||
explode(event.blockList(), event.getEntity() instanceof TNTPrimed);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,7 +82,6 @@ public class TNTListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.TNT).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.TNT).isWithDefault(TNTMode.ALLOW)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.TNT.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.TNT).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
+8
-15
@@ -21,11 +21,9 @@ package de.steamwar.bausystem.features.region;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.config.BauServer;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.RegionUtils;
|
||||
import de.steamwar.bausystem.region.flags.Flag;
|
||||
import de.steamwar.bausystem.region.flags.TestblockMode;
|
||||
import de.steamwar.bausystem.region.utils.RegionExtensionType;
|
||||
import de.steamwar.bausystem.utils.PasteBuilder;
|
||||
import de.steamwar.command.PreviousArguments;
|
||||
@@ -108,7 +106,13 @@ public class TestblockCommand extends SWCommand {
|
||||
region.getRegionData().setTestblockSchematic(node);
|
||||
}
|
||||
|
||||
PasteBuilder.ClipboardProvider clipboardProvider = node == null ? PasteBuilder.ClipboardProvider.EMPTY : PasteBuilder.ClipboardProvider.schematic(node);
|
||||
PasteBuilder.ClipboardProvider clipboardProvider;
|
||||
if (node == null) {
|
||||
clipboardProvider = new PasteBuilder.FileProvider(region.getTestblockArea().getResetFile());
|
||||
} else {
|
||||
clipboardProvider = new PasteBuilder.SchematicProvider(node);
|
||||
}
|
||||
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider)
|
||||
.ignoreAir(ignoreAir)
|
||||
@@ -116,7 +120,7 @@ public class TestblockCommand extends SWCommand {
|
||||
.removeTNT(removeTNT)
|
||||
.removeWater(removeWater)
|
||||
.color(region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
region.getTestblockArea().reset(p.getLocation(), pasteBuilder, regionExtensionType == RegionExtensionType.EXTENSION);
|
||||
region.getTestblockArea().reset(pasteBuilder, regionExtensionType == RegionExtensionType.EXTENSION);
|
||||
RegionUtils.message(region, "REGION_TB_DONE");
|
||||
} catch (SecurityException e) {
|
||||
BauSystem.MESSAGE.send("REGION_TB_ERROR", p);
|
||||
@@ -169,17 +173,6 @@ public class TestblockCommand extends SWCommand {
|
||||
|
||||
private Region regionCheck(Player player) {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
if (region.getRegionData().has(Flag.TESTBLOCK).isWritable() && region.getRegionData().get(Flag.TESTBLOCK).isWithDefault(TestblockMode.NO_VALUE)) {
|
||||
Point minPoint = region.getArea().getMinPoint(false);
|
||||
Point maxPoint = region.getArea().getMaxPoint(false);
|
||||
// TODO: Check if empty!
|
||||
int half = minPoint.getZ() + (maxPoint.getZ() - minPoint.getZ()) / 2;
|
||||
if (player.getLocation().getBlockZ() <= half) {
|
||||
region.getRegionData().set(Flag.TESTBLOCK, TestblockMode.SOUTH);
|
||||
} else {
|
||||
region.getRegionData().set(Flag.TESTBLOCK, TestblockMode.NORTH);
|
||||
}
|
||||
}
|
||||
if (region.getTestblockArea().isEmpty()) {
|
||||
BauSystem.MESSAGE.send("REGION_TB_NO_REGION", player);
|
||||
return null;
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.region;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.flags.Flag;
|
||||
import de.steamwar.bausystem.region.flags.TestblockMode;
|
||||
import de.steamwar.bausystem.utils.ScoreboardElement;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@Linked
|
||||
public class TestblockScoreboardElement implements ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public ScoreboardGroup getGroup() {
|
||||
return ScoreboardGroup.REGION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.TESTBLOCK).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.TESTBLOCK).is(TestblockMode.NO_VALUE)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.TESTBLOCK.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.TESTBLOCK).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
}
|
||||
-1
@@ -51,7 +51,6 @@ public class WaterDestroyListener implements Listener, ScoreboardElement {
|
||||
|
||||
@Override
|
||||
public String get(Region region, Player p) {
|
||||
if (region.getRegionData().has(Flag.WATER_DESTROY).notVisibleInScoreboard()) return null;
|
||||
if (region.getRegionData().get(Flag.WATER_DESTROY).isWithDefault(WaterDestroyMode.ALLOW)) return null;
|
||||
return "§e" + BauSystem.MESSAGE.parse(Flag.WATER_DESTROY.getChatValue(), p) + "§8: " + BauSystem.MESSAGE.parse(region.getRegionData().get(Flag.WATER_DESTROY).getWithDefault().getChatValue(), p);
|
||||
}
|
||||
|
||||
+10
-2
@@ -50,8 +50,16 @@ public class ResetBauGuiItem extends BauGuiItem {
|
||||
|
||||
@Override
|
||||
public boolean click(ClickType click, Player p) {
|
||||
p.closeInventory();
|
||||
resetCommand.genericResetCommand(p);
|
||||
if (click == ClickType.LEFT) {
|
||||
p.closeInventory();
|
||||
resetCommand.genericResetCommand(p);
|
||||
} else {
|
||||
SchematicSelector selector = new SchematicSelector(p, SchematicSelector.selectSchematic(), node -> {
|
||||
p.closeInventory();
|
||||
resetCommand.schematicResetCommand(p, node);
|
||||
});
|
||||
selector.open();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+4
-7
@@ -20,7 +20,6 @@
|
||||
package de.steamwar.bausystem.features.simulator;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.SWUtils;
|
||||
@@ -48,6 +47,7 @@ import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -72,9 +72,6 @@ import java.util.stream.Collectors;
|
||||
public class SimulatorCursor implements Listener {
|
||||
|
||||
private static final World WORLD = Bukkit.getWorlds().get(0);
|
||||
private Class<?> position = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
|
||||
private Class<?> look = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Rot");
|
||||
private Class<?> positionLook = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
|
||||
|
||||
private static Map<Player, CursorType> cursorType = Collections.synchronizedMap(new HashMap<>());
|
||||
private static Map<Player, REntityServer> cursors = Collections.synchronizedMap(new HashMap<>());
|
||||
@@ -89,9 +86,9 @@ public class SimulatorCursor implements Listener {
|
||||
calcCursor(player);
|
||||
return object;
|
||||
};
|
||||
TinyProtocol.instance.addFilter(position, function);
|
||||
TinyProtocol.instance.addFilter(look, function);
|
||||
TinyProtocol.instance.addFilter(positionLook, function);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, function);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Rot.class, function);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, function);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
||||
+13
-4
@@ -19,14 +19,15 @@
|
||||
|
||||
package de.steamwar.bausystem.features.simulator.execute;
|
||||
|
||||
import com.destroystokyo.paper.event.server.ServerTickEndEvent;
|
||||
import com.destroystokyo.paper.event.server.ServerTickStartEvent;
|
||||
import de.steamwar.bausystem.features.simulator.data.Simulator;
|
||||
import de.steamwar.bausystem.features.simulator.data.SimulatorElement;
|
||||
import de.steamwar.bausystem.features.simulator.data.SimulatorGroup;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||
import de.steamwar.bausystem.features.tracer.TraceRecorder;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.utils.TickEndEvent;
|
||||
import de.steamwar.bausystem.utils.TickStartEvent;
|
||||
import de.steamwar.bausystem.utils.TickManager;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -109,8 +110,13 @@ public class SimulatorExecutor implements Listener {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean tickStartRan = false;
|
||||
|
||||
@EventHandler
|
||||
public void onTickStart(TickStartEvent event) {
|
||||
public void onServerTickStart(ServerTickStartEvent event) {
|
||||
if (TickManager.impl.isFrozen()) return;
|
||||
tickStartRan = true;
|
||||
|
||||
long currentTick = TPSUtils.currentRealTick.get();
|
||||
Map<Integer, List<SimulatorAction>> actionsToRun = tickStartActions.remove(currentTick);
|
||||
if (actionsToRun == null) return;
|
||||
@@ -123,7 +129,10 @@ public class SimulatorExecutor implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTickEnd(TickEndEvent event) {
|
||||
public void onServerTickEnd(ServerTickEndEvent event) {
|
||||
if (!tickStartRan) return;
|
||||
tickStartRan = false;
|
||||
|
||||
long currentTick = TPSUtils.currentRealTick.get() - 1;
|
||||
List<SimulatorAction> actionsToRun = tickEndActions.remove(currentTick);
|
||||
if (actionsToRun == null) return;
|
||||
|
||||
+2
-2
@@ -33,12 +33,12 @@ public class StabFinalizer extends StabStep {
|
||||
@Override
|
||||
protected void start() {
|
||||
try {
|
||||
PasteBuilder.ClipboardProvider clipboardProvider = PasteBuilder.ClipboardProvider.clipboard(data.clipboard);
|
||||
PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard);
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider);
|
||||
if (data.region.getRegionData().has(Flag.COLOR).isReadable()) {
|
||||
pasteBuilder.color(data.region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
}
|
||||
data.region.getTestblockArea().reset(null, pasteBuilder, true);
|
||||
data.region.getTestblockArea().reset(pasteBuilder, true);
|
||||
} catch (SecurityException e) {
|
||||
stop();
|
||||
throw e;
|
||||
|
||||
+2
-2
@@ -71,12 +71,12 @@ public class StabGenerator extends StabStep implements Listener {
|
||||
@Override
|
||||
protected void start() {
|
||||
try {
|
||||
PasteBuilder.ClipboardProvider clipboardProvider = PasteBuilder.ClipboardProvider.clipboard(data.clipboard);
|
||||
PasteBuilder.ClipboardProvider clipboardProvider = new PasteBuilder.ClipboardProviderImpl(data.clipboard);
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(clipboardProvider);
|
||||
if (data.region.getRegionData().has(Flag.COLOR).isReadable()) {
|
||||
pasteBuilder.color(data.region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
}
|
||||
data.region.getTestblockArea().reset(null, pasteBuilder, true);
|
||||
data.region.getTestblockArea().reset(pasteBuilder, true);
|
||||
} catch (SecurityException e) {
|
||||
stop();
|
||||
throw e;
|
||||
|
||||
+2
@@ -150,11 +150,13 @@ public class SimulatorObserverGui extends SimulatorScrollGui<ObserverPhase> {
|
||||
Consumer<Integer> setter = observerPhase::setTickOffset;
|
||||
return new SWItem[] {
|
||||
new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
|
||||
observer,
|
||||
new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
|
||||
|
||||
+5
@@ -32,6 +32,7 @@ import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -97,6 +98,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Tick Offset
|
||||
int offset = observer.getTickOffset();
|
||||
inventory.setItem(10, new SWItem(SWItem.getDye(offset < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.setTickOffset(Math.min(max, offset + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -113,6 +115,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(19, offsetItem);
|
||||
|
||||
inventory.setItem(28, new SWItem(SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
@@ -120,6 +123,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Order
|
||||
int order = observer.getOrder();
|
||||
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -138,6 +142,7 @@ public class SimulatorObserverPhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(22, orderItem);
|
||||
|
||||
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
+9
@@ -28,6 +28,7 @@ import de.steamwar.data.CMDs;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -67,6 +68,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
|
||||
// Base Tick
|
||||
int baseTicks = observer.getBaseTick();
|
||||
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -81,6 +83,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
|
||||
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
|
||||
inventory.setItem(18, baseTick);
|
||||
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
|
||||
observer.changeBaseTicks(-baseTicks);
|
||||
} else {
|
||||
@@ -91,6 +94,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
|
||||
|
||||
//Pos X
|
||||
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -102,12 +106,14 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
//Pos Y
|
||||
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.move(0, clickType.isShiftClick() ? 5 : 1, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
|
||||
@@ -119,12 +125,14 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.move(0, clickType.isShiftClick() ? -5 : -1, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
//Pos Z
|
||||
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.move(0, 0, clickType.isShiftClick() ? 5 : 1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.ENABLED_OR_DISABLED));
|
||||
@@ -136,6 +144,7 @@ public class SimulatorObserverSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
observer.move(0, 0, clickType.isShiftClick() ? -5 : -1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
+2
@@ -165,11 +165,13 @@ public class SimulatorRedstoneGui extends SimulatorScrollGui<SimulatorRedstoneGu
|
||||
Consumer<Integer> setter = redstoneSubPhase.place ? redstoneSubPhase.phase::setTickOffset : redstoneSubPhase.phase::setLifetime;
|
||||
return new SWItem[] {
|
||||
new SWItem(SWItem.getDye(getter.get() < max ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
setter.accept(Math.min(max, getter.get() + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
|
||||
redstone,
|
||||
new SWItem(SWItem.getDye(getter.get() > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
setter.accept(Math.max(min, getter.get() - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
|
||||
|
||||
+7
@@ -31,6 +31,7 @@ import de.steamwar.data.CMDs;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -98,6 +99,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Tick Offset
|
||||
int offset = redstone.getTickOffset();
|
||||
inventory.setItem(10, new SWItem(SWItem.getDye(offset < maxOffset ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.setTickOffset(Math.min(maxOffset, offset + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -114,6 +116,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(19, offsetItem);
|
||||
|
||||
inventory.setItem(28, new SWItem(SWItem.getDye(offset > min ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.setTickOffset(Math.max(min, offset - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
@@ -121,6 +124,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Lifetime
|
||||
int lifetime = redstone.getLifetime();
|
||||
inventory.setItem(11, new SWItem(SWItem.getDye(lifetime < maxLifetime ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.setLifetime(Math.min(maxLifetime, lifetime + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -137,6 +141,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(20, lifetimeItem);
|
||||
|
||||
inventory.setItem(29, new SWItem(SWItem.getDye(lifetime > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.setLifetime(Math.max(0, lifetime - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
@@ -144,6 +149,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Order
|
||||
int order = redstone.getOrder();
|
||||
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -162,6 +168,7 @@ public class SimulatorRedstonePhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(22, orderItem);
|
||||
|
||||
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
+9
@@ -28,6 +28,7 @@ import de.steamwar.data.CMDs;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -66,6 +67,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
|
||||
// Base Tick
|
||||
int baseTicks = redstone.getBaseTick();
|
||||
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -80,6 +82,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
|
||||
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
|
||||
inventory.setItem(18, baseTick);
|
||||
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
|
||||
redstone.changeBaseTicks(-baseTicks);
|
||||
} else {
|
||||
@@ -90,6 +93,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
|
||||
|
||||
//Pos X
|
||||
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.move(clickType.isShiftClick() ? 5 : 1, 0, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -101,12 +105,14 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.move(clickType.isShiftClick() ? -5 : -1, 0, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
//Pos Y
|
||||
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.move(0, clickType.isShiftClick() ? 5 : 1, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -118,12 +124,14 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.move(0, clickType.isShiftClick() ? -5 : -1, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
//Pos Z
|
||||
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.move(0, 0, clickType.isShiftClick() ? 5 : 1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -135,6 +143,7 @@ public class SimulatorRedstoneSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
redstone.move(0, 0, clickType.isShiftClick() ? -5 : -1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
+2
@@ -138,11 +138,13 @@ public class SimulatorTNTGui extends SimulatorScrollGui<TNTPhase> {
|
||||
|
||||
return new SWItem[]{
|
||||
new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8:§e +5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tntSetting.setCount(tntSetting.getCount() + (clickType.isShiftClick() ? 5 : 1));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED),
|
||||
tnt,
|
||||
new SWItem(SWItem.getDye(tntSetting.getCount() > 1 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8:§e -5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tntSetting.setCount(Math.max(1, tntSetting.getCount() - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED),
|
||||
|
||||
+13
@@ -31,6 +31,7 @@ import de.steamwar.data.CMDs;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -78,6 +79,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Count
|
||||
int count = tnt.getCount();
|
||||
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setCount(count + (clickType.isShiftClick() ? 5 : 1));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -94,6 +96,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(18, countItem);
|
||||
|
||||
inventory.setItem(27, new SWItem(SWItem.getDye(count > 1 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setCount(Math.max(1, count - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
@@ -101,6 +104,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Tick Offset
|
||||
int offset = tnt.getTickOffset();
|
||||
inventory.setItem(10, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setTickOffset(offset + (clickType.isShiftClick() ? 5 : 1));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -117,6 +121,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(19, offsetItem);
|
||||
|
||||
inventory.setItem(28, new SWItem(SWItem.getDye(offset > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setTickOffset(Math.max(0, offset - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
@@ -124,6 +129,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Lifetime
|
||||
int lifetime = tnt.getLifetime();
|
||||
inventory.setItem(11, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setLifetime(lifetime + (clickType.isShiftClick() ? 5 : 1));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -140,6 +146,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(20, lifetimeItem);
|
||||
|
||||
inventory.setItem(29, new SWItem(SWItem.getDye(lifetime > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setLifetime(Math.max(1, lifetime - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
@@ -147,6 +154,7 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
//Order
|
||||
int order = tnt.getOrder();
|
||||
inventory.setItem(13, new SWItem(SWItem.getDye(order < SimulatorPhase.ORDER_LIMIT ? 10 : 8), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setOrder(Math.min(SimulatorPhase.ORDER_LIMIT, order + (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -165,30 +173,35 @@ public class SimulatorTNTPhaseSettingsGui extends SimulatorBaseGui {
|
||||
inventory.setItem(22, orderItem);
|
||||
|
||||
inventory.setItem(31, new SWItem(SWItem.getDye(order > -SimulatorPhase.ORDER_LIMIT ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setOrder(Math.max(-SimulatorPhase.ORDER_LIMIT, order - (clickType.isShiftClick() ? 5 : 1)));
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
//Jump
|
||||
SWItem jumpX = new SWItem(tnt.isXJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump X§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setXJump(!tnt.isXJump());
|
||||
SimulatorWatcher.update(simulator);
|
||||
});
|
||||
inventory.setItem(33, jumpX);
|
||||
|
||||
SWItem jumpY = new SWItem(tnt.isYJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Y§8: " + (tnt.isYJump() ? "§aon" : "§coff"), clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setYJump(!tnt.isYJump());
|
||||
SimulatorWatcher.update(simulator);
|
||||
});
|
||||
inventory.setItem(16, jumpY);
|
||||
|
||||
SWItem jumpZ = new SWItem(tnt.isZJump() ? Material.LIME_WOOL : Material.RED_WOOL, "§7TNT §eJump Z§8: " + (tnt.isZJump() ? "§aon" : "§coff"), clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setZJump(!tnt.isZJump());
|
||||
SimulatorWatcher.update(simulator);
|
||||
});
|
||||
inventory.setItem(35, jumpZ);
|
||||
|
||||
SWItem jumpAll = new SWItem(Material.TNT, "§7TNT §eJump §8: " + (tnt.hasJump() ? "§aon" : "§coff"), clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.setJump(!tnt.hasJump());
|
||||
SimulatorWatcher.update(simulator);
|
||||
});
|
||||
|
||||
+9
@@ -28,6 +28,7 @@ import de.steamwar.data.CMDs;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -75,6 +76,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
|
||||
// Base Tick
|
||||
int baseTicks = tnt.getBaseTick();
|
||||
inventory.setItem(9, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.changeBaseTicks(clickType.isShiftClick() ? 5 : 1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -89,6 +91,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
|
||||
baseTick.getItemStack().setAmount(Math.max(1, Math.min(baseTicks, 64)));
|
||||
inventory.setItem(18, baseTick);
|
||||
inventory.setItem(27, new SWItem(SWItem.getDye(baseTicks > 0 ? 1 : 8), "§e-1", Arrays.asList("§7Shift§8: §e-5"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
if (baseTicks - (clickType.isShiftClick() ? 5 : 1) < 0) {
|
||||
tnt.changeBaseTicks(-baseTicks);
|
||||
} else {
|
||||
@@ -136,6 +139,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
|
||||
|
||||
// Pos X
|
||||
inventory.setItem(15, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.move(clickType.isShiftClick() ? 0.0625 : 1, 0, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -147,12 +151,14 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(33, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.move(clickType.isShiftClick() ? -0.0625 : -1, 0, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
// Pos Y
|
||||
inventory.setItem(16, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.move(0, clickType.isShiftClick() ? 0.0625 : 1, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -164,12 +170,14 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(34, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.move(0, clickType.isShiftClick() ? -0.0625 : -1, 0);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
// Pos Z
|
||||
inventory.setItem(17, new SWItem(SWItem.getDye(10), "§e+1", Arrays.asList("§7Shift§8: §e+0.0625"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.move(0, 0, clickType.isShiftClick() ? 0.0625 : 1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.INCREMENT_OR_DISABLED));
|
||||
@@ -181,6 +189,7 @@ public class SimulatorTNTSettingsGui extends SimulatorBaseGui {
|
||||
}, this).open();
|
||||
}));
|
||||
inventory.setItem(35, new SWItem(SWItem.getDye(1), "§e-1", Arrays.asList("§7Shift§8: §e-0.0625"), false, clickType -> {
|
||||
if (clickType == ClickType.DOUBLE_CLICK) return;
|
||||
tnt.move(0, 0, clickType.isShiftClick() ? -0.0625 : -1);
|
||||
SimulatorWatcher.update(simulator);
|
||||
}).setCustomModelData(CMDs.Simulator.DECREMENT_OR_DISABLED));
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class BlockBoundingBox {
|
||||
addPixel(Material.END_STONE.createBlockData(), 0, 0, 0, 16, 16, 16, null);
|
||||
|
||||
addPixel(NMSWrapper.impl.pathMaterial().createBlockData(), 0, 0, 0, 16, 15, 16, createItem("LAUFBAU_BLOCK_GRASS_PATH", NMSWrapper.impl.pathMaterial()));
|
||||
addPixel(Material.SOUL_SAND.createBlockData(), 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SOUL_SAND", Material.SOUL_SAND));
|
||||
addPixel(Material.MUD.createBlockData(), 0, 0, 0, 16, 14, 16, createItem("LAUFBAU_BLOCK_SOUL_SAND", Material.SOUL_SAND));
|
||||
|
||||
Cocoa cocoaNorth = (Cocoa) Material.COCOA.createBlockData();
|
||||
cocoaNorth.setAge(2);
|
||||
|
||||
+2
@@ -25,12 +25,14 @@ import de.steamwar.bausystem.shared.Pair;
|
||||
import de.steamwar.bausystem.utils.WorldEditUtils;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
@Linked
|
||||
@MinVersion(19)
|
||||
public class LaufbauCommand extends SWCommand {
|
||||
|
||||
public LaufbauCommand() {
|
||||
|
||||
+2
-4
@@ -20,13 +20,13 @@
|
||||
package de.steamwar.bausystem.features.smartplace;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.configplayer.Config;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import net.minecraft.network.protocol.game.ServerboundUseItemOnPacket;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@@ -83,13 +83,11 @@ public class SmartPlaceListener implements Listener {
|
||||
IGNORED.remove(Material.BARRIER);
|
||||
}
|
||||
|
||||
private static final Class<?> useItem = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket");
|
||||
|
||||
private static final Set<Player> SMART_PLACING = new HashSet<>();
|
||||
private static final Set<Player> WAS_EXECUTED = new HashSet<>();
|
||||
|
||||
public SmartPlaceListener() {
|
||||
TinyProtocol.instance.addFilter(useItem, (player, packet) -> {
|
||||
TinyProtocol.instance.addFilter(ServerboundUseItemOnPacket.class, (player, packet) -> {
|
||||
if(!Permission.BUILD.hasPermission(player)) return packet;
|
||||
if (!Config.getInstance().get(player).getPlainValueOrDefault("smartPlace", false)) return packet;
|
||||
RayTraceResult rayTraceResult = player.rayTraceBlocks(6);
|
||||
|
||||
+11
-1
@@ -135,7 +135,7 @@ public abstract class ViewFlag {
|
||||
}
|
||||
|
||||
Location secoundLocation;
|
||||
if (previousVelocity.getX() >= previousVelocity.getZ()) {
|
||||
if (Math.abs(previousVelocity.getX()) >= Math.abs(previousVelocity.getZ())) {
|
||||
secoundLocation = previous.getLocation().clone().add(delta.getX(), delta.getY(), 0);
|
||||
} else {
|
||||
secoundLocation = previous.getLocation().clone().add(0, delta.getY(), delta.getZ());
|
||||
@@ -198,6 +198,16 @@ public abstract class ViewFlag {
|
||||
}
|
||||
};
|
||||
|
||||
public static ViewFlag HIGHLIGHT = new ViewFlag(true, false, "highlight", "h") {
|
||||
@Override
|
||||
public void modify(REntityServer server, List<TraceEntity> entities) {
|
||||
for (TraceEntity entity : entities) {
|
||||
entity.setGlowing(true);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Name of the flag
|
||||
*/
|
||||
|
||||
@@ -39,10 +39,7 @@ import lombok.Setter;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
+8
-22
@@ -21,7 +21,6 @@ package de.steamwar.bausystem.features.util;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.tpslimit.TPSUtils;
|
||||
import de.steamwar.bausystem.utils.BauMemberUpdateEvent;
|
||||
@@ -30,6 +29,7 @@ import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.core.ProtocolWrapper;
|
||||
import de.steamwar.core.SWPlayer;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -45,16 +45,6 @@ import java.util.function.BiFunction;
|
||||
@Linked
|
||||
public class NoClipCommand extends SWCommand implements Listener {
|
||||
|
||||
public static final Class<?> gameStateChange = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundGameEventPacket");
|
||||
private static final Reflection.Field<Float> floatFieldAccessor = Reflection.getField(gameStateChange, float.class, 0);
|
||||
|
||||
private static final Class<?> position = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
|
||||
private static final Class<?> positionLook = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
|
||||
private static final Class<?> useItem = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket");
|
||||
private static final Class<?> blockDig = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundPlayerActionPacket");
|
||||
private static final Class<?> windowClick = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundContainerClickPacket");
|
||||
private static final Class<?> setSlotStack = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSetCreativeModeSlotPacket");
|
||||
|
||||
public static class NoClipData implements SWPlayer.Component {
|
||||
private long lastTick = -1;
|
||||
|
||||
@@ -75,8 +65,8 @@ public class NoClipCommand extends SWCommand implements Listener {
|
||||
noClipData.lastTick = TPSUtils.currentTick.get();
|
||||
return o;
|
||||
};
|
||||
TinyProtocol.instance.addFilter(position, first);
|
||||
TinyProtocol.instance.addFilter(positionLook, first);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, first);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, first);
|
||||
|
||||
BiFunction<Player, Object, Object> second = (player, o) -> {
|
||||
NoClipData noClipData = SWPlayer.of(player).getComponent(NoClipData.class).orElse(null);
|
||||
@@ -85,9 +75,9 @@ public class NoClipCommand extends SWCommand implements Listener {
|
||||
noClipData.lastTick = TPSUtils.currentTick.get();
|
||||
return o;
|
||||
};
|
||||
TinyProtocol.instance.addFilter(useItem, second);
|
||||
TinyProtocol.instance.addFilter(blockDig, second);
|
||||
TinyProtocol.instance.addFilter(windowClick, second);
|
||||
TinyProtocol.instance.addFilter(ServerboundUseItemOnPacket.class, second);
|
||||
TinyProtocol.instance.addFilter(ServerboundPlayerActionPacket.class, second);
|
||||
TinyProtocol.instance.addFilter(ServerboundContainerClickPacket.class, second);
|
||||
|
||||
BiFunction<Player, Object, Object> third = (player, o) -> {
|
||||
if (SWPlayer.of(player).hasComponent(NoClipData.class)) {
|
||||
@@ -95,7 +85,7 @@ public class NoClipCommand extends SWCommand implements Listener {
|
||||
}
|
||||
return o;
|
||||
};
|
||||
TinyProtocol.instance.addFilter(setSlotStack, third);
|
||||
TinyProtocol.instance.addFilter(ServerboundSetCreativeModeSlotPacket.class, third);
|
||||
}
|
||||
|
||||
@Register(help = true)
|
||||
@@ -107,13 +97,9 @@ public class NoClipCommand extends SWCommand implements Listener {
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
NMSWrapper.impl.setPlayerBuildAbilities(player);
|
||||
|
||||
Object gameStateChangeObject = Reflection.newInstance(gameStateChange);
|
||||
NMSWrapper.impl.setGameStateChangeReason(gameStateChangeObject);
|
||||
floatFieldAccessor.set(gameStateChangeObject, 1F);
|
||||
|
||||
swPlayer.setComponent(new NoClipData());
|
||||
BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player);
|
||||
TinyProtocol.instance.sendPacket(player, gameStateChangeObject);
|
||||
TinyProtocol.instance.sendPacket(player, new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, 1F));
|
||||
pseudoGameMode(player, GameMode.SPECTATOR);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,8 +22,8 @@ package de.steamwar.bausystem.features.util.items;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.features.util.KillAllCommand;
|
||||
import de.steamwar.bausystem.linkage.BauGuiItem;
|
||||
import de.steamwar.bausystem.features.util.RegionSelectionType;
|
||||
import de.steamwar.bausystem.linkage.BauGuiItem;
|
||||
import de.steamwar.inventory.SWItem;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
|
||||
@@ -22,7 +22,6 @@ package de.steamwar.bausystem.features.warp;
|
||||
import de.steamwar.bausystem.region.RegionSystem;
|
||||
import de.steamwar.bausystem.worlddata.WorldData;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
@@ -36,20 +35,14 @@ public class Warp {
|
||||
private static Map<String, Warp> warpMap = new HashMap<>();
|
||||
|
||||
public static void enable() {
|
||||
Warp worldSpawn = new Warp("WorldSpawn") {
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return RegionSystem.INSTANCE.getWorldSpawn();
|
||||
}
|
||||
};
|
||||
Warp worldSpawn = new Warp("WorldSpawn");
|
||||
worldSpawn.setLocation(RegionSystem.INSTANCE.getWorldSpawn());
|
||||
worldSpawn.setMat(Material.NETHER_STAR);
|
||||
warpMap.put("WorldSpawn", worldSpawn);
|
||||
}
|
||||
|
||||
private String name;
|
||||
@Setter
|
||||
private Location location;
|
||||
@Setter
|
||||
private Material mat;
|
||||
|
||||
private Warp(String name) {
|
||||
@@ -98,13 +91,21 @@ public class Warp {
|
||||
return warpMap.get(name);
|
||||
}
|
||||
|
||||
public void setMat(Material mat) {
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
public void setLocation(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
warpMap.remove(name);
|
||||
WorldData.getWarpData().remove(name);
|
||||
}
|
||||
|
||||
public void teleport(Player player) {
|
||||
player.teleport(getLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
player.playSound(getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||
player.teleport(location, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
player.playSound(location, Sound.ENTITY_ENDERMAN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -19,11 +19,11 @@
|
||||
|
||||
package de.steamwar.bausystem.features.world;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.api.Enable;
|
||||
import net.minecraft.network.protocol.game.ClientboundContainerClosePacket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
|
||||
@@ -32,8 +32,7 @@ public class AntiCursorReCentering implements Enable {
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
Class<?> closeWindow = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundContainerClosePacket");
|
||||
TinyProtocol.instance.addFilter(closeWindow, (player, object) -> {
|
||||
TinyProtocol.instance.addFilter(ClientboundContainerClosePacket.class, (player, object) -> {
|
||||
if (player.getOpenInventory().getTopInventory().getType() == InventoryType.CRAFTING) {
|
||||
return object;
|
||||
}
|
||||
|
||||
+5
-2
@@ -119,8 +119,11 @@ public class BauScoreboard implements Listener {
|
||||
@Override
|
||||
public String getTitle() {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
if (region.getRegionData().has(Flag.COLOR).notVisibleInScoreboard()) return "§eSteam§8War";
|
||||
String colorCode = "§" + region.getRegionData().get(Flag.COLOR).getWithDefault().getColorCode();
|
||||
if (region.getType().isGlobal()) return "§eSteam§8War";
|
||||
String colorCode = "§e";
|
||||
if (region.getRegionData().has(Flag.COLOR).isReadable()) {
|
||||
colorCode = "§" + region.getRegionData().get(Flag.COLOR).orElse(ColorMode.PINK).getColorCode();
|
||||
}
|
||||
return colorCode + "■ §eSteam§8War " + colorCode + "■"; // ■
|
||||
}
|
||||
});
|
||||
|
||||
+2
-2
@@ -19,17 +19,17 @@
|
||||
|
||||
package de.steamwar.bausystem.features.world;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.bausystem.utils.NMSWrapper;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import net.minecraft.network.protocol.game.ClientboundExplodePacket;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
@Linked
|
||||
public class NoCreativeKnockback {
|
||||
|
||||
public NoCreativeKnockback() {
|
||||
TinyProtocol.instance.addFilter(Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket"), (player, o) -> {
|
||||
TinyProtocol.instance.addFilter(ClientboundExplodePacket.class, (player, o) -> {
|
||||
if (player.getGameMode() != GameMode.CREATIVE) return o;
|
||||
return NMSWrapper.impl.resetExplosionKnockback(o);
|
||||
});
|
||||
|
||||
+12
-28
@@ -19,13 +19,14 @@
|
||||
|
||||
package de.steamwar.bausystem.features.world;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.bausystem.utils.PlaceItemUtils;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundSignUpdatePacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
@@ -37,6 +38,8 @@ import org.bukkit.block.data.Directional;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.block.sign.SignSide;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
@@ -45,24 +48,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@Linked
|
||||
@MinVersion(20)
|
||||
public class SignEditFrom20 implements Listener {
|
||||
|
||||
private static final Class<?> blockPosition = Reflection.getClass("net.minecraft.core.BlockPos");
|
||||
private static final Class<?> craftBlock = Reflection.getClass("org.bukkit.craftbukkit.block.CraftBlock");
|
||||
private static final Class<?> craftWorld = Reflection.getClass("org.bukkit.craftbukkit.CraftWorld");
|
||||
private static final Class<?> generatorAccess = Reflection.getClass("net.minecraft.world.level.LevelAccessor");
|
||||
private static final Reflection.Method getPosition = Reflection.getTypedMethod(craftBlock, "getPosition", blockPosition);
|
||||
private static final Reflection.Method getWorldHandle = Reflection.getTypedMethod(craftWorld, "getHandle", null);
|
||||
private static final Reflection.Method at = Reflection.getTypedMethod(craftBlock, "at", craftBlock, generatorAccess, blockPosition);
|
||||
|
||||
private static final Class<?> openSign = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket");
|
||||
private static final Reflection.Field<?> blockPositionFieldAccessor = Reflection.getField(openSign, blockPosition, 0);
|
||||
private static final Reflection.Field<?> sideFieldAccessor = Reflection.getField(openSign, boolean.class, 0);
|
||||
|
||||
private static final Class<?> updateSign = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSignUpdatePacket");
|
||||
private static final Reflection.Field<?> getBlockPositionFieldAccessor = Reflection.getField(updateSign, blockPosition, 0);
|
||||
private static final Reflection.Field<String[]> stringFieldAccessor = Reflection.getField(updateSign, String[].class, 0);
|
||||
public class SignEdit implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void editSign(PlayerInteractEvent event) {
|
||||
@@ -93,10 +79,8 @@ public class SignEditFrom20 implements Listener {
|
||||
sign.update(true);
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
Object openSignObject = Reflection.newInstance(openSign);
|
||||
blockPositionFieldAccessor.set(openSignObject, getPosition.invoke(block));
|
||||
sideFieldAccessor.set(openSignObject, side == Side.FRONT);
|
||||
TinyProtocol.instance.sendPacket(player, openSignObject);
|
||||
ClientboundOpenSignEditorPacket packet = new ClientboundOpenSignEditorPacket(((CraftBlock) block).getPosition(), side == Side.FRONT);
|
||||
TinyProtocol.instance.sendPacket(player, packet);
|
||||
}, 1);
|
||||
|
||||
}
|
||||
@@ -117,14 +101,14 @@ public class SignEditFrom20 implements Listener {
|
||||
}
|
||||
|
||||
{
|
||||
TinyProtocol.instance.addFilter(updateSign, (player, o) -> {
|
||||
TinyProtocol.instance.addTypedFilter(ServerboundSignUpdatePacket.class, (player, o) -> {
|
||||
Bukkit.getScheduler().runTask(BauSystem.getInstance(), () -> {
|
||||
String[] lines = stringFieldAccessor.get(o);
|
||||
|
||||
Block signLoc = (Block) at.invoke(null, getWorldHandle.invoke(player.getWorld()), getBlockPositionFieldAccessor.get(o));
|
||||
ServerLevel serverLevel = ((CraftWorld) player.getWorld()).getHandle();
|
||||
Block signLoc = CraftBlock.at(serverLevel, o.getPos());
|
||||
if (!signLoc.getType().name().contains("SIGN"))
|
||||
return;
|
||||
|
||||
String[] lines = o.getLines();
|
||||
Sign sign = ((Sign) signLoc.getState());
|
||||
SignSide signSide = sign.getSide(signSide(player, signLoc));
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.world;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.Permission;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MaxVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
|
||||
@Linked
|
||||
@MaxVersion(19)
|
||||
public class SignEditUntil19 implements Listener {
|
||||
|
||||
private static final Class<?> blockPosition = Reflection.getClass("net.minecraft.core.BlockPos");
|
||||
private static final Class<?> craftBlock = Reflection.getClass("org.bukkit.craftbukkit.block.CraftBlock");
|
||||
private static final Class<?> craftWorld = Reflection.getClass("org.bukkit.craftbukkit.CraftWorld");
|
||||
private static final Class<?> generatorAccess = Reflection.getClass("net.minecraft.world.level.LevelAccessor");
|
||||
private static final Reflection.Method getPosition = Reflection.getTypedMethod(craftBlock, "getPosition", blockPosition);
|
||||
private static final Reflection.Method getWorldHandle = Reflection.getTypedMethod(craftWorld, "getHandle", null);
|
||||
private static final Reflection.Method at = Reflection.getTypedMethod(craftBlock, "at", craftBlock, generatorAccess, blockPosition);
|
||||
|
||||
private static final Class<?> openSign = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket");
|
||||
private static final Reflection.Field<?> blockPositionFieldAccessor = Reflection.getField(openSign, blockPosition, 0);
|
||||
|
||||
private static final Class<?> updateSign = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundSignUpdatePacket");
|
||||
private static final Reflection.Field<?> getBlockPositionFieldAccessor = Reflection.getField(updateSign, blockPosition, 0);
|
||||
private static final Reflection.Field<String[]> stringFieldAccessor = Reflection.getField(updateSign, String[].class, 0);
|
||||
|
||||
@EventHandler
|
||||
public void editSign(PlayerInteractEvent event) {
|
||||
if (!event.getPlayer().isSneaking()) return;
|
||||
if (event.getClickedBlock() == null || !event.getClickedBlock().getType().name().contains("SIGN")) return;
|
||||
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && (event.getItem() == null || event.getItem().getType() == Material.AIR) || event.getAction() == Action.LEFT_CLICK_BLOCK) {
|
||||
event.setCancelled(true);
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
edit(event.getPlayer(), event.getClickedBlock());
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void edit(Player player, Block block) {
|
||||
if (!Permission.BUILD.hasPermission(player)) return;
|
||||
Sign sign = (org.bukkit.block.Sign) block.getState();
|
||||
String[] lines = sign.getLines();
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
sign.setLine(i, lines[i].replace('§', '&'));
|
||||
}
|
||||
sign.update(true);
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
||||
Object openSignObject = Reflection.newInstance(openSign);
|
||||
blockPositionFieldAccessor.set(openSignObject, getPosition.invoke(block));
|
||||
TinyProtocol.instance.sendPacket(player, openSignObject);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
{
|
||||
TinyProtocol.instance.addFilter(updateSign, (player, o) -> {
|
||||
Bukkit.getScheduler().runTask(BauSystem.getInstance(), () -> {
|
||||
String[] lines = stringFieldAccessor.get(o);
|
||||
|
||||
Block signLoc = (Block) at.invoke(null, getWorldHandle.invoke(player.getWorld()), getBlockPositionFieldAccessor.get(o));
|
||||
if (!signLoc.getType().name().contains("SIGN"))
|
||||
return;
|
||||
|
||||
org.bukkit.block.Sign sign = ((Sign) signLoc.getState());
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
sign.setLine(i, ChatColor.translateAlternateColorCodes('&', lines[i]));
|
||||
}
|
||||
sign.update();
|
||||
});
|
||||
return o;
|
||||
});
|
||||
}
|
||||
}
|
||||
-189
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.worldedit;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||
import de.steamwar.core.SWPlayer;
|
||||
import de.steamwar.core.WorldEditRenderer;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.MinVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Linked
|
||||
@MinVersion(20)
|
||||
public class SelectAdjacent implements Listener {
|
||||
|
||||
private Vector[] FACES = {
|
||||
new Vector(1, 0, 0),
|
||||
new Vector(-1, 0, 0),
|
||||
new Vector(0, 1, 0),
|
||||
new Vector(0, -1, 0),
|
||||
new Vector(0, 0, 1),
|
||||
new Vector(0, 0, -1),
|
||||
|
||||
new Vector(1, 1, 0),
|
||||
new Vector(1, -1, 0),
|
||||
new Vector(1, 0, 1),
|
||||
new Vector(1, 0, -1),
|
||||
new Vector(-1, 1, 0),
|
||||
new Vector(-1, -1, 0),
|
||||
new Vector(-1, 0, 1),
|
||||
new Vector(-1, 0, -1),
|
||||
new Vector(0, 1, 1),
|
||||
new Vector(0, 1, -1),
|
||||
new Vector(0, -1, 1),
|
||||
new Vector(0, -1, -1),
|
||||
};
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
if (!event.hasItem()) return;
|
||||
if (event.getItem().getType() != Material.WOODEN_AXE) return;
|
||||
if (!event.getPlayer().isSneaking()) return;
|
||||
if (event.getAction() != Action.LEFT_CLICK_BLOCK) return;
|
||||
Material material = event.getPlayer().getInventory().getItemInOffHand().getType();
|
||||
Selector selector;
|
||||
if (material.isAir()) {
|
||||
selector = new Selector(event.getClickedBlock(), event.getPlayer(), __ -> true);
|
||||
} else {
|
||||
selector = new Selector(event.getClickedBlock(), event.getPlayer(), type -> type == material);
|
||||
}
|
||||
SWPlayer.of(event.getPlayer()).setComponent(selector);
|
||||
}
|
||||
|
||||
private class Selector implements SWPlayer.Component {
|
||||
|
||||
private static final int MAX_BLOCKS = 500_000;
|
||||
|
||||
private int minX;
|
||||
private int minY;
|
||||
private int minZ;
|
||||
private int maxX;
|
||||
private int maxY;
|
||||
private int maxZ;
|
||||
|
||||
private BukkitTask bukkitTask;
|
||||
private Predicate<Material> predicate;
|
||||
private Set<Location> seen = new HashSet<>();
|
||||
private Set<Location> toCalc = new HashSet<>();
|
||||
|
||||
private Region.Area area;
|
||||
|
||||
public Selector(Block block, Player player, Predicate<Material> predicate) {
|
||||
this.predicate = predicate;
|
||||
toCalc.add(block.getLocation());
|
||||
minX = block.getX();
|
||||
minY = block.getY();
|
||||
minZ = block.getZ();
|
||||
maxX = block.getX();
|
||||
maxY = block.getY();
|
||||
maxZ = block.getZ();
|
||||
|
||||
Region region = Region.getRegion(block.getLocation());
|
||||
area = Region.Area.EMPTY;
|
||||
if (region.getBuildArea().inRegion(block.getLocation(), true)) {
|
||||
area = region.getBuildArea();
|
||||
} else if (region.getTestblockArea().inRegion(block.getLocation(), true)) {
|
||||
area = region.getTestblockArea();
|
||||
} else if (region.getArea().inRegion(block.getLocation(), true)) {
|
||||
area = region.getArea();
|
||||
}
|
||||
|
||||
bukkitTask = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
|
||||
run();
|
||||
|
||||
long volume = (long)(maxX - minX + 1) * (long)(maxY - minY + 1) * (long)(maxZ - minZ + 1);
|
||||
player.sendTitle("", "§e" + volume + " §7Blocks", 0, 5, 0);
|
||||
|
||||
Point minPoint = new Point(minX, minY, minZ);
|
||||
Point maxPoint = new Point(maxX, maxY, maxZ);
|
||||
|
||||
FlatteningWrapper.impl.setSelection(player, minPoint, maxPoint);
|
||||
WorldEditRenderer.renderPlayer(player);
|
||||
|
||||
// boolean finished = toCalc.stream().allMatch(location -> {
|
||||
// return location.getBlockX() >= minX && location.getBlockY() >= minY && location.getBlockZ() >= minZ &&
|
||||
// location.getBlockX() <= maxX && location.getBlockY() <= maxY && location.getBlockZ() <= maxZ;
|
||||
// });
|
||||
|
||||
if (toCalc.isEmpty() || seen.size() > MAX_BLOCKS) {
|
||||
bukkitTask.cancel();
|
||||
player.sendTitle("§aDone", "§e" + volume + " §7Blocks", 0, 20, 5);
|
||||
SWPlayer.of(player).removeComponent(Selector.class);
|
||||
}
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
bukkitTask.cancel();
|
||||
}
|
||||
|
||||
private void run() {
|
||||
Set<Location> current = toCalc;
|
||||
toCalc = new HashSet<>();
|
||||
|
||||
for (Location location : current) {
|
||||
Block block = location.getBlock();
|
||||
if (block.isEmpty() || block.isLiquid()) continue;
|
||||
if (!predicate.test(block.getType())) continue;
|
||||
seen.add(location);
|
||||
if (!area.inRegion(block.getLocation(), true)) continue;
|
||||
|
||||
minX = Math.min(minX, location.getBlockX());
|
||||
maxX = Math.max(maxX, location.getBlockX());
|
||||
minY = Math.min(minY, location.getBlockY());
|
||||
maxY = Math.max(maxY, location.getBlockY());
|
||||
minZ = Math.min(minZ, location.getBlockZ());
|
||||
maxZ = Math.max(maxZ, location.getBlockZ());
|
||||
|
||||
for (Vector face : FACES) {
|
||||
Block next = block.getRelative(face.getBlockX(), face.getBlockY(), face.getBlockZ());
|
||||
if (next.isEmpty() || next.isLiquid()) continue;
|
||||
if (!predicate.test(next.getType())) continue;
|
||||
Location loc = next.getLocation();
|
||||
if (seen.contains(loc)) continue;
|
||||
toCalc.add(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnmount(SWPlayer player) {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
package de.steamwar.bausystem.features.xray;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.techhider.TechHiderCommand;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
@@ -32,6 +31,7 @@ import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.linkage.LinkedInstance;
|
||||
import de.steamwar.techhider.TechHider;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -95,9 +95,6 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen
|
||||
});
|
||||
}
|
||||
|
||||
private static final Class<?> position = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$Pos");
|
||||
private static final Class<?> positionLook = Reflection.getClass("net.minecraft.network.protocol.game.ServerboundMovePlayerPacket$PosRot");
|
||||
|
||||
{
|
||||
BiFunction<Player, Object, Object> positionSetter = (player, o) -> {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
@@ -110,8 +107,8 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen
|
||||
return o;
|
||||
};
|
||||
|
||||
TinyProtocol.instance.addFilter(position, positionSetter);
|
||||
TinyProtocol.instance.addFilter(positionLook, positionSetter);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, positionSetter);
|
||||
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, positionSetter);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Linked
|
||||
public class BackupScheduler implements Enable {
|
||||
@@ -44,7 +43,6 @@ public class BackupScheduler implements Enable {
|
||||
Iterator<Region> regionsToBackup = RegionSystem.INSTANCE.getRegions()
|
||||
.filter(region -> region.getRegionData().has(Flag.CHANGED).isReadable())
|
||||
.filter(region -> region.getRegionData().get(Flag.CHANGED).isWithDefault(ChangedMode.HAS_CHANGE))
|
||||
.collect(Collectors.toList())
|
||||
.iterator();
|
||||
if (!regionsToBackup.hasNext()) return;
|
||||
doBackup(regionsToBackup);
|
||||
|
||||
@@ -48,26 +48,14 @@ public class Point {
|
||||
return new Point(blockVector3.getBlockX(), blockVector3.getBlockY(), blockVector3.getBlockZ());
|
||||
}
|
||||
|
||||
public Point setY(int y) {
|
||||
return new Point(this.x, y, this.z);
|
||||
}
|
||||
|
||||
public Point add(int x, int y, int z) {
|
||||
return new Point(this.x + x, this.y + y, this.z + z);
|
||||
}
|
||||
|
||||
public Point add(Point point) {
|
||||
return add(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
public Point subtract(int x, int y, int z) {
|
||||
return new Point(this.x - x, this.y - y, this.z - z);
|
||||
}
|
||||
|
||||
public Point subtract(Point point) {
|
||||
return subtract(point.x, point.y, point.z);
|
||||
}
|
||||
|
||||
public Point divide(int factor) {
|
||||
return new Point(x / factor, y / factor, z / factor);
|
||||
}
|
||||
|
||||
@@ -24,16 +24,16 @@ import de.steamwar.bausystem.utils.FlatteningWrapper;
|
||||
import de.steamwar.bausystem.utils.PasteBuilder;
|
||||
import de.steamwar.sql.GameModeConfig;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface Region extends RegionDataStore {
|
||||
public interface Region {
|
||||
|
||||
static Stream<Region> getRegions() {
|
||||
return RegionSystem.INSTANCE.getRegions();
|
||||
@@ -76,9 +76,6 @@ public interface Region extends RegionDataStore {
|
||||
|
||||
interface Area {
|
||||
|
||||
int WORLD_MIN_Y = Bukkit.getWorlds().get(0).getMinHeight();
|
||||
int WORLD_MAX_Y = Bukkit.getWorlds().get(0).getMaxHeight();
|
||||
|
||||
Area EMPTY = new Area() {
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
@@ -111,7 +108,12 @@ public interface Region extends RegionDataStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void place(Location location, PasteBuilder pasteBuilder, boolean extension) {
|
||||
public File getResetFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(PasteBuilder pasteBuilder, boolean extension) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,24 +148,15 @@ public interface Region extends RegionDataStore {
|
||||
return true;
|
||||
}
|
||||
|
||||
default boolean inRegion(int x, int z, boolean extension) {
|
||||
Point minPoint = getMinPoint(extension);
|
||||
Point maxPoint = getMaxPoint(extension);
|
||||
if (x < minPoint.getX() || x > maxPoint.getX()) return false;
|
||||
if (z < minPoint.getZ() || z > maxPoint.getZ()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default Clipboard copy(boolean extension) {
|
||||
return FlatteningWrapper.impl.copy(getMinPoint(extension), getMaxPoint(extension), getCopyPoint());
|
||||
}
|
||||
|
||||
default void reset(Location location, PasteBuilder pasteBuilder, boolean extension) {
|
||||
place(location, pasteBuilder, extension);
|
||||
}
|
||||
@Nullable
|
||||
File getResetFile();
|
||||
|
||||
void place(Location location, PasteBuilder pasteBuilder, boolean extension);
|
||||
void reset(PasteBuilder pasteBuilder, boolean extension);
|
||||
|
||||
default void forEachChunk(BiConsumer<Integer, Integer> executor) {
|
||||
Point minPoint = getMinPoint(false);
|
||||
|
||||
@@ -22,19 +22,14 @@ package de.steamwar.bausystem.region;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import javax.annotation.CheckReturnValue;
|
||||
import javax.annotation.Nullable;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface RegionBackups {
|
||||
|
||||
DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy.MM.dd' 'HH:mm:ss");
|
||||
|
||||
@RequiredArgsConstructor
|
||||
enum BackupType {
|
||||
MANUAL(5),
|
||||
@@ -44,44 +39,22 @@ public interface RegionBackups {
|
||||
public final int maxBackups;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
abstract class Backup implements RegionDataStore, Comparable<Backup> {
|
||||
abstract class Backup {
|
||||
@NonNull
|
||||
protected final BackupType type;
|
||||
private final BackupType type;
|
||||
|
||||
@NonNull
|
||||
protected final String name;
|
||||
private final String name;
|
||||
|
||||
@NonNull
|
||||
protected final RegionData regionData;
|
||||
|
||||
protected Backup(@NonNull BackupType type, @NonNull String name, @NonNull Function<Backup, RegionData> regionDataConstructor) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
regionData = regionDataConstructor.apply(this);
|
||||
}
|
||||
private final RegionData data;
|
||||
|
||||
@CheckReturnValue
|
||||
public abstract boolean load();
|
||||
|
||||
@Override
|
||||
public final void save() {
|
||||
}
|
||||
|
||||
public abstract long getCreationTime();
|
||||
|
||||
@Override
|
||||
public int compareTo(Backup o) {
|
||||
return Long.compare(getCreationTime(), o.getCreationTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void load(RegionData regionData) {
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S3038") // This forces everybody to implement 'delete' for Backups!
|
||||
@Override
|
||||
public abstract void delete(Location location);
|
||||
public abstract void delete();
|
||||
}
|
||||
|
||||
@CheckReturnValue
|
||||
@@ -91,7 +64,7 @@ public interface RegionBackups {
|
||||
List<Backup> list();
|
||||
|
||||
@Nullable
|
||||
Backup get(@NonNull String name);
|
||||
Backup get(String name);
|
||||
|
||||
RegionBackups EMPTY = new RegionBackups() {
|
||||
@Override
|
||||
@@ -106,7 +79,7 @@ public interface RegionBackups {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Backup get(@NonNull String name) {
|
||||
public Backup get(String name) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,42 +22,81 @@ package de.steamwar.bausystem.region;
|
||||
import de.steamwar.bausystem.region.flags.Flag;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import lombok.NonNull;
|
||||
import yapion.hierarchy.types.YAPIONObject;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class RegionData {
|
||||
|
||||
protected RegionDataStore store;
|
||||
|
||||
private final List<Property<?, ?>> properties = new ArrayList<>();
|
||||
|
||||
protected final YAPIONObject data;
|
||||
protected final YAPIONObject flagData;
|
||||
protected final Runnable onChange;
|
||||
protected final Map<Flag<?>, Flag.Value<?>> flagMap = new HashMap<>();
|
||||
// TODO: These should be turned into an ECS like System because not every Region has them or should have them!
|
||||
protected final Property<SchematicNode, Integer> testblockSchematic = new Property<>("testblockSchematic", SchematicNode::byId, SchematicNode::getId);
|
||||
|
||||
protected RegionData(RegionDataStore store) {
|
||||
this.store = store;
|
||||
initialize();
|
||||
store.load(this);
|
||||
private final class Property<T, K> {
|
||||
private final String field;
|
||||
private final Function<K, T> loader;
|
||||
private final Function<T, K> writer;
|
||||
|
||||
private T value;
|
||||
|
||||
public Property(String field, Function<K, T> loader, Function<T, K> writer) {
|
||||
this.field = field;
|
||||
this.loader = loader;
|
||||
this.writer = writer;
|
||||
properties.add(this);
|
||||
}
|
||||
|
||||
public void load() {
|
||||
if (flagData.containsKey(field)) {
|
||||
value = loader.apply(flagData.getPlainValue(field));
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void set(T value) {
|
||||
this.value = value;
|
||||
if (value == null) {
|
||||
flagData.remove(field);
|
||||
} else {
|
||||
flagData.put(field, writer.apply(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void setStore(RegionDataStore store) {
|
||||
this.store = store;
|
||||
store.save();
|
||||
private Property<SchematicNode, Integer> testblockSchematic = new Property<>("testblockSchematic", SchematicNode::byId, SchematicNode::getId);
|
||||
|
||||
protected RegionData(YAPIONObject data, Runnable onChange) {
|
||||
this.data = data;
|
||||
this.flagData = data.getObjectOrSetDefault("flagStorage", new YAPIONObject());
|
||||
this.onChange = onChange;
|
||||
initialize();
|
||||
for (final Flag flag : Flag.getFlags()) {
|
||||
if (!has(flag).isWritable()) continue;
|
||||
try {
|
||||
String s = flagData.getPlainValue(flag.name());
|
||||
flagMap.put(flag, flag.valueOfValue(s));
|
||||
} catch (Exception e) {
|
||||
flagMap.put(flag, (Flag.Value<?>) flag.getDefaultValue());
|
||||
}
|
||||
}
|
||||
properties.forEach(Property::load);
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
}
|
||||
|
||||
/**
|
||||
* All connected Regions are required to have the same type as their RegionData.
|
||||
*/
|
||||
protected Stream<Region> connectedRegions() {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public abstract <T extends Enum<T> & Flag.Value<T>> RegionFlagPolicy has(@NonNull Flag<T> flag);
|
||||
|
||||
@@ -66,15 +105,11 @@ public abstract class RegionData {
|
||||
*/
|
||||
public final <T extends Enum<T> & Flag.Value<T>> boolean set(@NonNull Flag<T> flag, @NonNull T value) {
|
||||
if (has(flag).isWritable()) {
|
||||
boolean needsSave = flagMap.put(flag, value) != value;
|
||||
if (needsSave) store.save();
|
||||
|
||||
connectedRegions().forEach(region -> {
|
||||
if (region.getRegionData().flagMap.put(flag, value) != value) {
|
||||
region.save();
|
||||
}
|
||||
});
|
||||
return needsSave;
|
||||
if (flagMap.put(flag, value) != value) {
|
||||
flagData.put(flag.name(), value.name());
|
||||
onChange.run();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -85,94 +120,33 @@ public abstract class RegionData {
|
||||
}
|
||||
|
||||
public final void clear() {
|
||||
Set<Flag> remove = new HashSet<>();
|
||||
for (Flag flag : Flag.getFlags()) {
|
||||
if (has(flag).isWritable()) {
|
||||
flagMap.remove(flag);
|
||||
remove.add(flag);
|
||||
flagData.remove(flag.name());
|
||||
}
|
||||
}
|
||||
initialize();
|
||||
properties.forEach(property -> property.set(null));
|
||||
store.save();
|
||||
|
||||
connectedRegions().forEach(region -> {
|
||||
region.getRegionData().flagMap.keySet().removeAll(remove);
|
||||
region.getRegionData().initialize();
|
||||
region.getRegionData().properties.forEach(property -> property.set(null));
|
||||
region.save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method only copies all flags and properties from this into other without saving other afterward.
|
||||
* TODO: If {@link #connectedRegions()} is overridden this method will not work correctly!
|
||||
*/
|
||||
public final void copyInto(RegionData other) {
|
||||
if (this == other) return;
|
||||
other.flagMap.clear();
|
||||
other.flagMap.putAll(flagMap);
|
||||
// TODO: This might not be correct, needs to be investigated
|
||||
other.properties.clear();
|
||||
other.properties.addAll(properties);
|
||||
onChange.run();
|
||||
}
|
||||
|
||||
public final Map<Flag<?>, Flag.Value<?>> getBackedMap() {
|
||||
return flagMap;
|
||||
}
|
||||
|
||||
public final List<Property<Object, Object>> getBackedProperties() {
|
||||
return (List) properties;
|
||||
}
|
||||
|
||||
public final SchematicNode getTestblockSchematic() {
|
||||
public SchematicNode getTestblockSchematic() {
|
||||
return testblockSchematic.get();
|
||||
}
|
||||
|
||||
public final void setTestblockSchematic(SchematicNode schematic) {
|
||||
public void setTestblockSchematic(SchematicNode schematic) {
|
||||
testblockSchematic.set(schematic);
|
||||
store.save();
|
||||
onChange.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
StringBuilder st = new StringBuilder();
|
||||
st.append(getClass().getSimpleName()).append("{");
|
||||
st.append("flagMap=").append(flagMap);
|
||||
for (Property<?, ?> p : properties) {
|
||||
st.append(p);
|
||||
}
|
||||
st.append("}");
|
||||
return st.toString();
|
||||
}
|
||||
|
||||
public final class Property<T, K> {
|
||||
public final String field;
|
||||
public final Function<K, T> loader;
|
||||
public final Function<T, K> writer;
|
||||
|
||||
private T value;
|
||||
|
||||
private Property(String field, Function<K, T> loader, Function<T, K> writer) {
|
||||
this.field = field;
|
||||
this.loader = loader;
|
||||
this.writer = writer;
|
||||
properties.add(this);
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void set(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Object value = this.value;
|
||||
if (value != null) value = writer.apply((T) value);
|
||||
return ", " + field + "=" + value;
|
||||
}
|
||||
return getClass().getSimpleName() + "{" +
|
||||
"flagMap=" + flagMap +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.region;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
public interface RegionDataStore {
|
||||
void save();
|
||||
void load(RegionData regionData);
|
||||
default void delete(Location location) {
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,4 @@ public enum RegionFlagPolicy {
|
||||
public boolean isApplicable() {
|
||||
return readable || writable;
|
||||
}
|
||||
|
||||
public boolean notVisibleInScoreboard() {
|
||||
return !writable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
package de.steamwar.bausystem.region;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.Core;
|
||||
import lombok.NonNull;
|
||||
import org.bukkit.Location;
|
||||
|
||||
@@ -28,15 +26,10 @@ import javax.annotation.CheckReturnValue;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface RegionSystem {
|
||||
|
||||
Logger LOGGER = BauSystem.getInstance().getLogger();
|
||||
|
||||
UUID GLOBAL_REGION_ID = new UUID(0, 0);
|
||||
|
||||
RegionSystem INSTANCE = init();
|
||||
|
||||
/**
|
||||
@@ -44,6 +37,11 @@ public interface RegionSystem {
|
||||
*/
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Saves anything that should be written to file on either CRIUSleepEvent or plugin disable.
|
||||
*/
|
||||
void save();
|
||||
|
||||
/**
|
||||
* Returns the Location to teleport players to when they first join or Warp to "WorldSpawn"
|
||||
*/
|
||||
@@ -76,63 +74,47 @@ public interface RegionSystem {
|
||||
@NonNull
|
||||
Stream<Region> getRegions();
|
||||
|
||||
/**
|
||||
* Only contains Regions of the same Type as the one you inputted.
|
||||
*/
|
||||
@NonNull
|
||||
Stream<Region> getConnectedRegions(Region region);
|
||||
|
||||
private static RegionSystem init() {
|
||||
if (Core.getVersion() >= 21) {
|
||||
// TODO: Add some kind of detection if the DynamicRegionSystem should be used!
|
||||
try {
|
||||
return (RegionSystem) Class.forName("de.steamwar.bausystem.region.DynamicRegionSystem").getConstructor().newInstance();
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||
InvocationTargetException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
try {
|
||||
return (RegionSystem) Class.forName("de.steamwar.bausystem.region.FixedRegionSystem").getConstructor().newInstance();
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||
InvocationTargetException e) {
|
||||
// Ignore
|
||||
return new RegionSystem() {
|
||||
@Override
|
||||
public void load() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Location getWorldSpawn() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getGlobalRegion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region get(Location location) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Region> getRegion(UUID id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Region> getRegions() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
return new RegionSystem() {
|
||||
@Override
|
||||
public void load() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Location getWorldSpawn() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getGlobalRegion() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region get(Location location) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Region> getRegion(UUID id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Region> getRegions() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Stream<Region> getConnectedRegions(Region region) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,50 +26,9 @@ import lombok.RequiredArgsConstructor;
|
||||
@Getter
|
||||
public enum RegionType {
|
||||
|
||||
GLOBAL(ConnectionType.Global),
|
||||
/**
|
||||
* This should not be used by the DynamicRegionSystem
|
||||
*/
|
||||
NORMAL(ConnectionType.Closed),
|
||||
|
||||
SPAWN(ConnectionType.Closed),
|
||||
SPAWN_PATH(ConnectionType.Path),
|
||||
SPAWN_EXTENSION(ConnectionType.Closed),
|
||||
PATH(ConnectionType.Path),
|
||||
|
||||
DRY(ConnectionType.Closed),
|
||||
DRY_SPECIAL(ConnectionType.Closed),
|
||||
WET(ConnectionType.Water),
|
||||
WET_SPECIAL(ConnectionType.Water),
|
||||
GLOBAL(true),
|
||||
NORMAL(false),
|
||||
;
|
||||
|
||||
private final ConnectionType connectionType;
|
||||
|
||||
public boolean isGlobal() {
|
||||
return this == GLOBAL;
|
||||
}
|
||||
|
||||
public boolean isDeletable() {
|
||||
return this == NORMAL || this == SPAWN_EXTENSION || this == PATH || this == DRY || this == DRY_SPECIAL || this == WET || this == WET_SPECIAL;
|
||||
}
|
||||
|
||||
public boolean isSpecial() {
|
||||
return this == DRY_SPECIAL || this == WET_SPECIAL;
|
||||
}
|
||||
|
||||
public boolean isSpawn() {
|
||||
return this == SPAWN || this == SPAWN_PATH || this == SPAWN_EXTENSION;
|
||||
}
|
||||
|
||||
public boolean isPath() {
|
||||
return this == PATH || this == SPAWN_PATH;
|
||||
}
|
||||
|
||||
public enum ConnectionType {
|
||||
Closed,
|
||||
Path,
|
||||
Water,
|
||||
Global,
|
||||
Garden,
|
||||
}
|
||||
private final boolean global;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@UtilityClass
|
||||
public class RegionUtils {
|
||||
@@ -59,12 +58,10 @@ public class RegionUtils {
|
||||
}
|
||||
|
||||
public void forEachInRegion(Region region, Consumer<Player> consumer) {
|
||||
Stream<? extends Player> players = Bukkit.getOnlinePlayers().stream();
|
||||
if (region.getType().isGlobal()) {
|
||||
players = players.filter(player -> Region.getRegion(player.getLocation()).getType().isGlobal());
|
||||
} else {
|
||||
players = players.filter(player -> region.getArea().inRegion(player.getLocation(), false));
|
||||
}
|
||||
players.forEach(consumer);
|
||||
Bukkit.getOnlinePlayers()
|
||||
.stream()
|
||||
.filter(player -> region.getArea().inRegion(player.getLocation(), false))
|
||||
.filter(player -> !region.getType().isGlobal() || Region.getRegion(player.getLocation()).getType().isGlobal())
|
||||
.forEach(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,34 +20,211 @@
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitWorld;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Waterlogged;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public interface FlatteningWrapper {
|
||||
FlatteningWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
public class FlatteningWrapper {
|
||||
public static final FlatteningWrapper impl = new FlatteningWrapper();
|
||||
|
||||
boolean isNoBook(ItemStack item);
|
||||
public boolean isNoBook(ItemStack item) {
|
||||
return item.getType() != Material.WRITABLE_BOOK && item.getType() != Material.WRITTEN_BOOK;
|
||||
}
|
||||
|
||||
boolean isUnpusheable(Material material);
|
||||
boolean isBreakingOnPush(Material material);
|
||||
private static final Set<Material> unpushable = new HashSet<>(Arrays.asList(Material.BARRIER, Material.BEACON, Material.COMMAND_BLOCK, Material.CHAIN_COMMAND_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.ENCHANTING_TABLE, Material.END_GATEWAY, Material.END_PORTAL, Material.ENDER_CHEST, Material.GRINDSTONE, Material.JIGSAW, Material.JUKEBOX, Material.NETHER_PORTAL, Material.OBSIDIAN, Material.STRUCTURE_VOID, Material.BARREL, Material.BEEHIVE, Material.BEE_NEST, Material.BLAST_FURNACE, Material.BREWING_STAND, Material.CHEST, Material.DAYLIGHT_DETECTOR, Material.DISPENSER, Material.DROPPER, Material.FURNACE, Material.HOPPER, Material.LECTERN, Material.SMOKER, Material.TRAPPED_CHEST));
|
||||
|
||||
boolean isWorldEditCommand(String command);
|
||||
void setSelection(Player p, Point minPoint, Point maxPoint);
|
||||
// TODO: FLOWER
|
||||
private static final Set<Material> breaking = new HashSet<>(Arrays.asList(Material.BAMBOO, Material.CACTUS, Material.CAKE, Material.CARVED_PUMPKIN, Material.CHORUS_FLOWER, Material.CHORUS_PLANT, Material.COBWEB, Material.COCOA, Material.DRAGON_EGG, Material.FIRE, Material.FLOWER_POT, Material.JACK_O_LANTERN, Material.LADDER, Material.LAVA, Material.LAVA, Material.LEVER, Material.LILY_PAD, Material.MELON, Material.NETHER_WART, Material.PUMPKIN, Material.COMPARATOR, Material.REDSTONE_WIRE, Material.REPEATER, Material.TORCH, Material.STRUCTURE_VOID, Material.SCAFFOLDING, Material.SEA_PICKLE, Material.SNOW, Material.SUGAR_CANE, Material.TORCH, Material.TRIPWIRE, Material.TRIPWIRE_HOOK, Material.TURTLE_EGG, Material.VINE, Material.WATER, Material.WHEAT));
|
||||
|
||||
Clipboard loadSchematic(File file);
|
||||
EditSession paste(PasteBuilder pasteBuilder);
|
||||
public boolean isUnpusheable(Material material) {
|
||||
if (unpushable.contains(material)) {
|
||||
return true;
|
||||
}
|
||||
String name = material.name();
|
||||
return name.contains("BANNER") || name.contains("SIGN");
|
||||
}
|
||||
|
||||
Clipboard copy(Point minPoint, Point maxPoint, Point copyPoint);
|
||||
boolean backup(Point minPoint, Point maxPoint, File file);
|
||||
public boolean isBreakingOnPush(Material material) {
|
||||
if (breaking.contains(material)) {
|
||||
return true;
|
||||
}
|
||||
String name = material.name();
|
||||
return name.contains("BED") || name.contains("BUTTON") || name.contains("CARPET") || (name.contains("DOOR") && !name.contains("TRAPDOOR")) || name.contains("HEAD") || name.contains("LEAVES") || name.contains("MUSHROOM") || name.contains("PRESSURE_PLATE") || name.contains("SHULKER_BOX");
|
||||
}
|
||||
|
||||
boolean inWater(World world, Vector tntPosition);
|
||||
public boolean isWorldEditCommand(String command) {
|
||||
if (command.startsWith("/")) {
|
||||
command = command.replaceFirst("/", "");
|
||||
}
|
||||
command = command.toLowerCase();
|
||||
return WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getCommandManager().containsCommand(command);
|
||||
}
|
||||
|
||||
private static final WorldEditPlugin WORLDEDIT_PLUGIN = Objects.requireNonNull((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit"));
|
||||
private static final BukkitWorld BUKKITWORLD = new BukkitWorld(Bukkit.getWorlds().get(0));
|
||||
|
||||
public void setSelection(Player p, Point minPoint, Point maxPoint) {
|
||||
WORLDEDIT_PLUGIN.getSession(p).setRegionSelector(BUKKITWORLD, new CuboidRegionSelector(BUKKITWORLD, minPoint.toBlockVector3(), maxPoint.toBlockVector3()));
|
||||
}
|
||||
|
||||
public Clipboard loadSchematic(File file) {
|
||||
Clipboard clipboard;
|
||||
try (ClipboardReader reader = Objects.requireNonNull(ClipboardFormats.findByFile(file)).getReader(new FileInputStream(file))) {
|
||||
clipboard = reader.read();
|
||||
} catch (NullPointerException | IOException e) {
|
||||
throw new SecurityException("Bausystem schematic not found", e);
|
||||
}
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
public EditSession paste(PasteBuilder pasteBuilder) {
|
||||
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(new BukkitWorld(Bukkit.getWorlds().get(0)), -1)) {
|
||||
Clipboard clipboard = pasteBuilder.getClipboard();
|
||||
|
||||
if (!pasteBuilder.getMappers().isEmpty()) {
|
||||
BlockVector3 minimum = clipboard.getRegion().getMinimumPoint();
|
||||
for (int x = 0; x < clipboard.getDimensions().getX(); x++) {
|
||||
for (int y = 0; y < clipboard.getDimensions().getY(); y++) {
|
||||
for (int z = 0; z < clipboard.getDimensions().getZ(); z++) {
|
||||
BlockVector3 pos = minimum.add(x, y, z);
|
||||
pasteBuilder.getMappers().forEach(mapper -> mapper.accept(clipboard, pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomicReference<BlockVector3> pastePoint = new AtomicReference<>();
|
||||
if (!pasteBuilder.getPredicates().isEmpty()) {
|
||||
e.setMask(new Mask() {
|
||||
@Override
|
||||
public boolean test(BlockVector3 blockVector3) {
|
||||
BaseBlock block = clipboard.getFullBlock(blockVector3.subtract(pastePoint.get()).add(clipboard.getRegion().getMinimumPoint()));
|
||||
String blockName = block.getBlockType().toString().toLowerCase();
|
||||
for (BiPredicate<BaseBlock, String> predicate : pasteBuilder.getPredicates()) {
|
||||
if (!predicate.test(block, blockName)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Mask copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Mask2D toMask2D() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ClipboardHolder ch = new ClipboardHolder(clipboard);
|
||||
BlockVector3 dimensions = clipboard.getDimensions();
|
||||
BlockVector3 v = BlockVector3.at(pasteBuilder.getPastPoint().getX(), pasteBuilder.getPastPoint().getY(), pasteBuilder.getPastPoint().getZ());
|
||||
BlockVector3 offset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
|
||||
if (pasteBuilder.isRotate()) {
|
||||
ch.setTransform(new AffineTransform().rotateY(180));
|
||||
v = v.add(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset.multiply(-1, 1, -1)).subtract(0, 0, 1);
|
||||
} else {
|
||||
v = v.subtract(dimensions.getX() / 2, 0, dimensions.getZ() / 2).subtract(offset);
|
||||
}
|
||||
pastePoint.set(v);
|
||||
|
||||
if (pasteBuilder.isReset()) {
|
||||
e.setBlocks((Region) new CuboidRegion(pasteBuilder.getMinPoint().toBlockVector3(), pasteBuilder.getMaxPoint().toBlockVector3()), Objects.requireNonNull(BlockTypes.AIR).getDefaultState().toBaseBlock());
|
||||
if (pasteBuilder.getWaterLevel() != 0) {
|
||||
e.setBlocks((Region) new CuboidRegion(pasteBuilder.getMinPoint().toBlockVector3(), pasteBuilder.getMaxPoint().toBlockVector3().withY(pasteBuilder.getWaterLevel())), Objects.requireNonNull(BlockTypes.WATER).getDefaultState().toBaseBlock());
|
||||
}
|
||||
}
|
||||
Operations.completeBlindly(ch.createPaste(e).to(v).ignoreAirBlocks(pasteBuilder.isIgnoreAir()).build());
|
||||
return e;
|
||||
} catch (WorldEditException e) {
|
||||
throw new SecurityException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public Clipboard copy(Point minPoint, Point maxPoint, Point copyPoint) {
|
||||
BukkitWorld bukkitWorld = new BukkitWorld(Bukkit.getWorlds().get(0));
|
||||
CuboidRegion region = new CuboidRegion(bukkitWorld, minPoint.toBlockVector3(), maxPoint.toBlockVector3());
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
try (EditSession e = WorldEdit.getInstance().getEditSessionFactory().getEditSession(bukkitWorld, -1)) {
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(
|
||||
e, region, clipboard, region.getMinimumPoint()
|
||||
);
|
||||
|
||||
copy.setCopyingEntities(false);
|
||||
copy.setCopyingBiomes(false);
|
||||
|
||||
Operations.complete(copy);
|
||||
clipboard.setOrigin(copyPoint.toBlockVector3());
|
||||
return clipboard;
|
||||
} catch (WorldEditException e) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean backup(Point minPoint, Point maxPoint, File file) {
|
||||
Clipboard clipboard = copy(minPoint, maxPoint, minPoint);
|
||||
try (ClipboardWriter writer = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) {
|
||||
writer.write(clipboard);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean inWater(org.bukkit.World world, Vector tntPosition) {
|
||||
Block block = world.getBlockAt(tntPosition.getBlockX(), tntPosition.getBlockY(), tntPosition.getBlockZ());
|
||||
if (block.getType() == Material.WATER)
|
||||
return true;
|
||||
|
||||
BlockData data = block.getBlockData();
|
||||
if (!(data instanceof Waterlogged))
|
||||
return false;
|
||||
|
||||
return ((Waterlogged) data).isWaterlogged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,25 +19,99 @@
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import de.steamwar.Reflection;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.datacomponent.item.ItemContainerContents;
|
||||
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundExplodePacket;
|
||||
import net.minecraft.server.level.ServerPlayerGameMode;
|
||||
import net.minecraft.world.entity.player.Abilities;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public interface NMSWrapper {
|
||||
NMSWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
void setInternalGameMode(Player player, GameMode gameMode);
|
||||
void setSlotToItemStack(Player player, Object o);
|
||||
public class NMSWrapper {
|
||||
public static final NMSWrapper impl = new NMSWrapper();
|
||||
|
||||
void setGameStateChangeReason(Object packet);
|
||||
void setPlayerBuildAbilities(Player player);
|
||||
private static final Reflection.Field<GameType> playerGameMode = Reflection.getField(ServerPlayerGameMode.class, GameType.class, 0);
|
||||
|
||||
Material pathMaterial();
|
||||
public void setInternalGameMode(Player player, GameMode gameMode) {
|
||||
playerGameMode.set(((CraftPlayer) player).getHandle().gameMode, GameType.byId(gameMode.getValue()));
|
||||
}
|
||||
|
||||
boolean checkItemStack(ItemStack item);
|
||||
public void setSlotToItemStack(Player player, Object o) {
|
||||
ClientboundContainerSetSlotPacket packetPlayInSetCreativeSlot = (ClientboundContainerSetSlotPacket) o;
|
||||
int index = packetPlayInSetCreativeSlot.getSlot();
|
||||
if (index >= 36 && index <= 44) {
|
||||
index -= 36;
|
||||
} else if (index > 44) {
|
||||
index -= 5;
|
||||
} else if (index <= 8) {
|
||||
index = index - 8 + 36;
|
||||
}
|
||||
player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.getItem()));
|
||||
if (index < 9) player.getInventory().setHeldItemSlot(index);
|
||||
player.updateInventory();
|
||||
}
|
||||
|
||||
Object resetExplosionKnockback(Object packet);
|
||||
public void setPlayerBuildAbilities(Player player) {
|
||||
Abilities abilities = (((CraftPlayer) player).getHandle()).getAbilities();
|
||||
abilities.mayBuild = true;
|
||||
abilities.mayfly = true;
|
||||
}
|
||||
|
||||
public Material pathMaterial() {
|
||||
return Material.DIRT_PATH;
|
||||
}
|
||||
|
||||
private static final int threshold = 2048;
|
||||
|
||||
public boolean checkItemStack(ItemStack item) {
|
||||
ItemContainerContents data = item.getData(DataComponentTypes.CONTAINER);
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drillDown(data.contents(), 0, 0) > threshold;
|
||||
}
|
||||
|
||||
private int drillDown(List<ItemStack> items, int layer, int start) {
|
||||
if (layer > 2) return start + threshold;
|
||||
int invalid = start;
|
||||
for (int i = start; i < items.size(); i++) {
|
||||
ItemStack item = items.get(i);
|
||||
if (item.isEmpty()) continue;
|
||||
|
||||
invalid += item.getAmount();
|
||||
|
||||
ItemContainerContents data = item.getData(DataComponentTypes.CONTAINER);
|
||||
if (data == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<ItemStack> subItems = data.contents();
|
||||
if (subItems.size() > 1) {
|
||||
invalid = drillDown(subItems, layer + 1, invalid);
|
||||
}
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
public Object resetExplosionKnockback(Object packet) {
|
||||
ClientboundExplodePacket explosion = (ClientboundExplodePacket) packet;
|
||||
|
||||
return new ClientboundExplodePacket(
|
||||
explosion.center(),
|
||||
Optional.empty(),
|
||||
explosion.explosionParticle(),
|
||||
explosion.explosionSound()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.function.BiPredicate;
|
||||
@Getter
|
||||
public class PasteBuilder {
|
||||
|
||||
private ClipboardProvider clipboardProvider;
|
||||
private final ClipboardProvider clipboardProvider;
|
||||
private Point pastPoint;
|
||||
private boolean rotate;
|
||||
private boolean ignoreAir;
|
||||
@@ -53,20 +53,10 @@ public class PasteBuilder {
|
||||
private List<BiPredicate<BaseBlock, String>> predicates = new ArrayList<>();
|
||||
private List<BiConsumer<Clipboard, BlockVector3>> mappers = new ArrayList<>();
|
||||
|
||||
public PasteBuilder() {
|
||||
clipboardProvider = ClipboardProvider.EMPTY;
|
||||
}
|
||||
|
||||
public PasteBuilder(@NonNull ClipboardProvider clipboardProvider) {
|
||||
this.clipboardProvider = clipboardProvider;
|
||||
}
|
||||
|
||||
public PasteBuilder with(@NonNull ClipboardProvider clipboardProvider) {
|
||||
if (this.clipboardProvider != ClipboardProvider.EMPTY) return this;
|
||||
this.clipboardProvider = clipboardProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasteBuilder pastePoint(Point point) {
|
||||
this.pastPoint = point;
|
||||
return this;
|
||||
@@ -102,16 +92,6 @@ public class PasteBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
private PasteBuilder predicates(List<BiPredicate<BaseBlock, String>> predicates) {
|
||||
this.predicates = predicates;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasteBuilder mappers(List<BiConsumer<Clipboard, BlockVector3>> mappers) {
|
||||
this.mappers = mappers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PasteBuilder only(BiPredicate<BaseBlock, String> predicate) {
|
||||
predicates.add(predicate);
|
||||
return this;
|
||||
@@ -202,27 +182,13 @@ public class PasteBuilder {
|
||||
}
|
||||
|
||||
public EditSession run() {
|
||||
if (pastPoint != null || minPoint != null) {
|
||||
return FlatteningWrapper.impl.paste(this);
|
||||
if (pastPoint == null) {
|
||||
throw new IllegalStateException("pastePoint is null");
|
||||
}
|
||||
throw new IllegalStateException("pastePoint is null");
|
||||
return FlatteningWrapper.impl.paste(this);
|
||||
}
|
||||
|
||||
public interface ClipboardProvider {
|
||||
ClipboardProvider EMPTY = new EmptyProvider();
|
||||
|
||||
static ClipboardProvider file(File file) {
|
||||
return new FileProvider(file);
|
||||
}
|
||||
|
||||
static ClipboardProvider schematic(SchematicNode schematic) {
|
||||
return new SchematicProvider(schematic);
|
||||
}
|
||||
|
||||
static ClipboardProvider clipboard(Clipboard clipboard) {
|
||||
return new ClipboardProviderImpl(clipboard);
|
||||
}
|
||||
|
||||
Clipboard getClipboard();
|
||||
|
||||
default <T extends ClipboardProvider> boolean is(Class<T> clazz) {
|
||||
@@ -234,22 +200,12 @@ public class PasteBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private static class EmptyProvider implements ClipboardProvider {
|
||||
private EmptyProvider() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class FileProvider implements ClipboardProvider {
|
||||
private final File file;
|
||||
private final Clipboard clipboard;
|
||||
|
||||
private FileProvider(File file) {
|
||||
public FileProvider(File file) {
|
||||
this.file = file;
|
||||
this.clipboard = FlatteningWrapper.impl.loadSchematic(file);
|
||||
}
|
||||
@@ -265,7 +221,7 @@ public class PasteBuilder {
|
||||
private final SchematicNode schematic;
|
||||
private final Clipboard clipboard;
|
||||
|
||||
private SchematicProvider(SchematicNode schematic) {
|
||||
public SchematicProvider(SchematicNode schematic) {
|
||||
this.schematic = schematic;
|
||||
try {
|
||||
this.clipboard = new SchematicData(schematic).load();
|
||||
@@ -284,7 +240,7 @@ public class PasteBuilder {
|
||||
public static class ClipboardProviderImpl implements ClipboardProvider {
|
||||
private final Clipboard clipboard;
|
||||
|
||||
private ClipboardProviderImpl(Clipboard clipboard) {
|
||||
public ClipboardProviderImpl(Clipboard clipboard) {
|
||||
this.clipboard = clipboard;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,15 @@ import de.steamwar.Reflection;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.*;
|
||||
import org.bukkit.block.Skull;
|
||||
import org.bukkit.block.data.*;
|
||||
import org.bukkit.block.data.type.Hopper;
|
||||
import org.bukkit.block.data.type.*;
|
||||
import org.bukkit.block.data.type.Hopper;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.CraftBlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockCanBuildEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
@@ -82,27 +86,23 @@ public class PlaceItemUtils {
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private static final Class<?> blockPosition = Reflection.getClass("net.minecraft.core.BlockPos");
|
||||
private static final Reflection.Constructor blockPositionConstructor = Reflection.getConstructor(blockPosition, int.class, int.class, int.class);
|
||||
private static final Class<?> craftBlock = Reflection.getClass("org.bukkit.craftbukkit.block.CraftBlockState");
|
||||
private static final Class<?> craftWorld = Reflection.getClass("org.bukkit.craftbukkit.CraftWorld");
|
||||
private static final Reflection.Field<?> positionAccessor = Reflection.getField(craftBlock, blockPosition, 0);
|
||||
private static final Reflection.Field<?> worldAccessor = Reflection.getField(craftBlock, craftWorld, 0);
|
||||
private static final Reflection.Field<?> positionAccessor = Reflection.getField(CraftBlockState.class, BlockPos.class, 0);
|
||||
private static final Reflection.Field<?> worldAccessor = Reflection.getField(CraftBlockState.class, CraftWorld.class, 0);
|
||||
|
||||
/**
|
||||
* Attempt to place an {@link ItemStack} the {@link Player} is holding against a {@link Block} inside the World.
|
||||
* This can be easily used inside the {@link org.bukkit.event.player.PlayerInteractEvent} to mimik placing a
|
||||
* block without any minecraft related GUI's etc. executing.
|
||||
*
|
||||
* @param player the Player placing the block
|
||||
* @param itemStack the ItemStack to be placed
|
||||
* @param against the Block at which the player aims (does not need to be in range of the player)
|
||||
* @param againstSide the BlockFace the player aims
|
||||
* @param hand the Hand the player is using
|
||||
* @param force allow illegal states to be created by placing the block
|
||||
* @param player the Player placing the block
|
||||
* @param itemStack the ItemStack to be placed
|
||||
* @param against the Block at which the player aims (does not need to be in range of the player)
|
||||
* @param againstSide the BlockFace the player aims
|
||||
* @param hand the Hand the player is using
|
||||
* @param force allow illegal states to be created by placing the block
|
||||
* @param applyPhysics apply physics while placing the block
|
||||
* @param rotateAway rotate everything in the opposite direction, so a block facing the Player will face away, and the other way round
|
||||
* @param playSound enables sound of placing
|
||||
* @param rotateAway rotate everything in the opposite direction, so a block facing the Player will face away, and the other way round
|
||||
* @param playSound enables sound of placing
|
||||
*/
|
||||
public PlaceItemResult placeItem(Player player, ItemStack itemStack, Block against, BlockFace againstSide, EquipmentSlot hand, boolean force, boolean applyPhysics, boolean rotateAway, boolean playSound) {
|
||||
// If the ItemStack is null or air we cannot place it
|
||||
@@ -288,7 +288,7 @@ public class PlaceItemUtils {
|
||||
} else {
|
||||
// If a BlockState is present set the Position and World to the Block you want to place
|
||||
Location blockLocation = block.getLocation();
|
||||
positionAccessor.set(blockState, blockPositionConstructor.invoke(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ()));
|
||||
positionAccessor.set(blockState, new BlockPos(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ()));
|
||||
worldAccessor.set(blockState, blockLocation.getWorld());
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ public class PlaceItemUtils {
|
||||
Location blockmin = block.getLocation();
|
||||
Location blockmax = block.getLocation().add(1.0, 1.0, 1.0);
|
||||
if (
|
||||
!(max.getX() <= blockmin.getX() || min.getX() >= blockmax.getX() ||
|
||||
!(max.getX() <= blockmin.getX() || min.getX() >= blockmax.getX() ||
|
||||
max.getY() <= blockmin.getY() || min.getY() >= blockmax.getY() ||
|
||||
max.getZ() <= blockmin.getZ() || min.getZ() >= blockmax.getZ())
|
||||
) {
|
||||
@@ -369,8 +369,8 @@ public class PlaceItemUtils {
|
||||
return usedForcePlace.get() ? PlaceItemResult.SUCCESS_FORCE : PlaceItemResult.SUCCESS;
|
||||
}
|
||||
|
||||
public BlockFace[] axis = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST };
|
||||
public BlockFace[] radial = { BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST };
|
||||
public BlockFace[] axis = {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST};
|
||||
public BlockFace[] radial = {BlockFace.NORTH, BlockFace.NORTH_EAST, BlockFace.EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH, BlockFace.SOUTH_WEST, BlockFace.WEST, BlockFace.NORTH_WEST};
|
||||
|
||||
public BlockFace yawToFace(float yaw) {
|
||||
return radial[Math.round(yaw / 45f) & 0x7];
|
||||
|
||||
@@ -19,16 +19,32 @@
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public interface PlaceItemWrapper {
|
||||
Map<Material, Material> ITEM_MATERIAL_TO_BLOCK_MATERIAL = new HashMap<>();
|
||||
Map<Material, Material> BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL = new HashMap<>();
|
||||
@UtilityClass
|
||||
public class PlaceItemWrapper {
|
||||
public static final Map<Material, Material> ITEM_MATERIAL_TO_BLOCK_MATERIAL = new HashMap<>();
|
||||
public static final Map<Material, Material> BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL = new HashMap<>();
|
||||
|
||||
PlaceItemWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
static {
|
||||
for (Material material : Material.values()) {
|
||||
if (!material.isBlock()) continue;
|
||||
if (material.isLegacy()) continue;
|
||||
BlockData blockData = material.createBlockData();
|
||||
Material placementMaterial = blockData.getPlacementMaterial();
|
||||
if (material == placementMaterial) continue;
|
||||
if (placementMaterial == Material.AIR) continue;
|
||||
if (placementMaterial.isItem() && !placementMaterial.isBlock()) {
|
||||
ITEM_MATERIAL_TO_BLOCK_MATERIAL.put(placementMaterial, material);
|
||||
}
|
||||
if (material.name().contains("WALL")) {
|
||||
BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(placementMaterial, material);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-6
@@ -20,19 +20,33 @@
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.BountifulWrapper;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import de.steamwar.entity.REntity;
|
||||
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface PlayerMovementWrapper {
|
||||
public class PlayerMovementWrapper {
|
||||
Class<?> teleportPacket = REntity.teleportPacket;
|
||||
Reflection.Field<Integer> teleportEntity = REntity.teleportEntity;
|
||||
BountifulWrapper.PositionSetter teleportPosition = REntity.teleportPosition;
|
||||
|
||||
PlayerMovementWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
public static final PlayerMovementWrapper impl = new PlayerMovementWrapper();
|
||||
|
||||
void setPosition(Player player, Object object);
|
||||
Object convertToOut(Player player, Object object);
|
||||
public void setPosition(Player player, Object object) {
|
||||
ServerboundMovePlayerPacket packetPlayInFlying = ((ServerboundMovePlayerPacket) object);
|
||||
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
if (packetPlayInFlying.hasPos) {
|
||||
serverPlayer.setPosRaw(packetPlayInFlying.x, packetPlayInFlying.y, packetPlayInFlying.z);
|
||||
}
|
||||
if (packetPlayInFlying.hasRot) {
|
||||
serverPlayer.setXRot(packetPlayInFlying.xRot);
|
||||
serverPlayer.setYRot(packetPlayInFlying.yRot);
|
||||
}
|
||||
}
|
||||
|
||||
public Object convertToOut(Player player, Object object) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
|
||||
public interface TickListener {
|
||||
|
||||
TickListener impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
|
||||
default void init() {
|
||||
}
|
||||
}
|
||||
@@ -19,28 +19,119 @@
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import net.minecraft.network.protocol.game.ClientboundTickingStatePacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ServerTickRateManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public interface TickManager extends Listener {
|
||||
TickManager impl = VersionDependent.getVersionImpl(BauSystem.getInstance());
|
||||
public class TickManager implements Listener {
|
||||
public static final TickManager impl = new TickManager();
|
||||
|
||||
void setTickRate(float tickRate);
|
||||
float getTickRate();
|
||||
private static final ServerTickRateManager manager = MinecraftServer.getServer().tickRateManager();
|
||||
private static final Reflection.Field<Long> remainingSprintTicks = Reflection.getField(ServerTickRateManager.class, long.class, 0);
|
||||
|
||||
boolean canFreeze();
|
||||
void setFreeze(boolean freeze);
|
||||
boolean isFrozen();
|
||||
private boolean blockTpsPacket = true;
|
||||
private int totalSteps;
|
||||
|
||||
void stepTicks(int ticks);
|
||||
boolean isStepping();
|
||||
private TickManager() {
|
||||
TinyProtocol.instance.addFilter(ClientboundTickingStatePacket.class, this::blockPacket);
|
||||
}
|
||||
|
||||
void sprintTicks(int ticks);
|
||||
boolean isSprinting();
|
||||
private Object blockPacket(Player player, Object packet) {
|
||||
if (blockTpsPacket) {
|
||||
return new ClientboundTickingStatePacket(20, manager.isFrozen());
|
||||
} else {
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
void setBlockTpsPacket(boolean block);
|
||||
long getRemainingTicks();
|
||||
long getDoneTicks();
|
||||
long getTotalTicks();
|
||||
public boolean canFreeze() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBlockTpsPacket(boolean block) {
|
||||
blockTpsPacket = block;
|
||||
if (blockTpsPacket) {
|
||||
ClientboundTickingStatePacket packet = new ClientboundTickingStatePacket(20, manager.isFrozen());
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
} else {
|
||||
ClientboundTickingStatePacket packet = new ClientboundTickingStatePacket(manager.tickrate(), manager.isFrozen());
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
}
|
||||
|
||||
public void setTickRate(float tickRate) {
|
||||
if (isFrozen()) {
|
||||
setFreeze(false);
|
||||
}
|
||||
manager.setTickRate(tickRate);
|
||||
}
|
||||
|
||||
public boolean isFrozen() {
|
||||
return manager.isFrozen();
|
||||
}
|
||||
|
||||
public void setFreeze(boolean freeze) {
|
||||
manager.setFrozen(freeze);
|
||||
}
|
||||
|
||||
public void stepTicks(int ticks) {
|
||||
if (manager.isSprinting()) {
|
||||
manager.stopSprinting();
|
||||
} else if (manager.isSteppingForward()) {
|
||||
manager.stopStepping();
|
||||
}
|
||||
this.totalSteps = ticks;
|
||||
manager.setFrozen(true);
|
||||
manager.stepGameIfPaused(ticks);
|
||||
manager.setFrozen(false);
|
||||
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), (bukkitTask) -> {
|
||||
if (manager.isSteppingForward()) return;
|
||||
manager.setFrozen(true);
|
||||
bukkitTask.cancel();
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
public void sprintTicks(int ticks) {
|
||||
if (manager.isSteppingForward()) {
|
||||
manager.stopStepping();
|
||||
} else if (manager.isSprinting()) {
|
||||
manager.stopSprinting();
|
||||
}
|
||||
this.totalSteps = ticks;
|
||||
manager.requestGameToSprint(ticks, true);
|
||||
}
|
||||
|
||||
public boolean isSprinting() {
|
||||
return manager.isSprinting();
|
||||
}
|
||||
|
||||
public boolean isStepping() {
|
||||
return manager.isSteppingForward();
|
||||
}
|
||||
|
||||
public float getTickRate() {
|
||||
return manager.tickrate();
|
||||
}
|
||||
|
||||
public long getRemainingTicks() {
|
||||
if (isSprinting()) {
|
||||
return remainingSprintTicks.get(manager);
|
||||
} else {
|
||||
return manager.frozenTicksToRun();
|
||||
}
|
||||
}
|
||||
|
||||
public long getDoneTicks() {
|
||||
return totalSteps - getRemainingTicks();
|
||||
}
|
||||
|
||||
public long getTotalTicks() {
|
||||
return totalSteps;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package de.steamwar.bausystem.utils;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
@@ -34,6 +33,7 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
|
||||
import de.steamwar.Reflection;
|
||||
import de.steamwar.bausystem.shared.Pair;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2024 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
options.isWarnings = false
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(libs.classindex)
|
||||
annotationProcessor(libs.classindex)
|
||||
|
||||
compileOnly(project(":BauSystem:BauSystem_Main", "default"))
|
||||
compileOnly(project(":SpigotCore", "default"))
|
||||
|
||||
compileOnly(libs.spigotapi)
|
||||
compileOnly(libs.axiom)
|
||||
compileOnly(libs.authlib)
|
||||
compileOnly(libs.viaapi)
|
||||
|
||||
compileOnly(libs.nms20)
|
||||
compileOnly(libs.fawe18)
|
||||
|
||||
implementation(libs.luaj)
|
||||
}
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.bausystem.features.region;
|
||||
|
||||
import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.RegionUtils;
|
||||
import de.steamwar.bausystem.region.flags.Flag;
|
||||
import de.steamwar.bausystem.region.flags.TestblockMode;
|
||||
import de.steamwar.bausystem.utils.PasteBuilder;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class WireframeCommand extends SWCommand {
|
||||
|
||||
public WireframeCommand() {
|
||||
super("wireframe");
|
||||
}
|
||||
|
||||
@Register
|
||||
public void wireframeCommand(@Validator Player p) {
|
||||
Region region = regionCheck(p);
|
||||
if (region == null) return;
|
||||
|
||||
try {
|
||||
PasteBuilder pasteBuilder = new PasteBuilder(PasteBuilder.ClipboardProvider.EMPTY)
|
||||
.ignoreAir(true)
|
||||
.color(region.getRegionData().get(Flag.COLOR).getWithDefault());
|
||||
region.getBuildArea().reset(p.getLocation(), pasteBuilder, false);
|
||||
RegionUtils.message(region, "REGION_TB_DONE");
|
||||
} catch (SecurityException e) {
|
||||
BauSystem.MESSAGE.send("REGION_TB_ERROR", p);
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed testblock", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Region regionCheck(Player player) {
|
||||
Region region = Region.getRegion(player.getLocation());
|
||||
if (region.getRegionData().has(Flag.TESTBLOCK).isWritable() && region.getRegionData().get(Flag.TESTBLOCK).isWithDefault(TestblockMode.NO_VALUE)) {
|
||||
Point minPoint = region.getArea().getMinPoint(false);
|
||||
Point maxPoint = region.getArea().getMaxPoint(false);
|
||||
// TODO: Check if empty!
|
||||
int half = minPoint.getZ() + (maxPoint.getZ() - minPoint.getZ()) / 2;
|
||||
if (player.getLocation().getBlockZ() <= half) {
|
||||
region.getRegionData().set(Flag.TESTBLOCK, TestblockMode.SOUTH);
|
||||
} else {
|
||||
region.getRegionData().set(Flag.TESTBLOCK, TestblockMode.NORTH);
|
||||
}
|
||||
}
|
||||
if (region.getTestblockArea().isEmpty()) {
|
||||
BauSystem.MESSAGE.send("REGION_TB_NO_REGION", player);
|
||||
return null;
|
||||
}
|
||||
return region;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user