mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-25 07:33:44 +02:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			fix/add-mi
			...
			feature/v7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 99133ee485 | ||
|   | e415dcc8a4 | ||
|   | f2da7cbdc9 | ||
|   | f175c24523 | ||
|   | f3f44b55c4 | ||
|   | b946f31fe3 | ||
|   | 6bb1ebe1a1 | ||
|   | ab64836fc0 | ||
|   | d932d2eae6 | 
							
								
								
									
										5
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ body: | ||||
|       value: | | ||||
|         Thanks for taking the time to fill out this bug report for PlotSquared! Fill out the following form to your best ability to help us fix the problem. | ||||
|         Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.github.io/plotsquared-documentation/). | ||||
|         Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://github.com/IntellectualSites/PlotSquared/security/policy) GitHub form! | ||||
|         Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://forms.gle/btgdRn9yhGtzEiGW8) form! | ||||
|  | ||||
|   - type: dropdown | ||||
|     attributes: | ||||
| @@ -27,9 +27,6 @@ body: | ||||
|       description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. | ||||
|       multiple: false | ||||
|       options: | ||||
|         - '1.20.1' | ||||
|         - '1.20' | ||||
|         - '1.19.4' | ||||
|         - '1.19.3' | ||||
|         - '1.19.2' | ||||
|         - '1.19.1' | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| name: Announce release on discord | ||||
| on: | ||||
|   release: | ||||
|     types: [ published ] | ||||
|     types: [published] | ||||
|  | ||||
| jobs: | ||||
|   send_announcement: | ||||
|     runs-on: ubuntu-latest | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/build-pr.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-pr.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,7 @@ | ||||
| name: Build PR | ||||
|  | ||||
| on: [ pull_request ] | ||||
|  | ||||
| jobs: | ||||
|   build_pr: | ||||
|     if: github.repository_owner == 'IntellectualSites' | ||||
|   | ||||
							
								
								
									
										14
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +1,10 @@ | ||||
| name: build | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - main | ||||
|       - v7 | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     if: github.repository_owner == 'IntellectualSites' | ||||
| @@ -28,7 +30,7 @@ jobs: | ||||
|             echo "STATUS=release" >> $GITHUB_ENV | ||||
|           fi | ||||
|       - name: Publish Release | ||||
|         if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} | ||||
|         if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} | ||||
|         run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository | ||||
|         env: | ||||
|           ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} | ||||
| @@ -36,13 +38,14 @@ jobs: | ||||
|           ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} | ||||
|           ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} | ||||
|       - name: Publish Snapshot | ||||
|         if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main' }} | ||||
|         if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7' }} | ||||
|         run: ./gradlew publishToSonatype | ||||
|         env: | ||||
|           ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} | ||||
|           ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} | ||||
|       - name: Publish core javadoc | ||||
|        # if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} | ||||
|        # if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} | ||||
|         if: ${{ runner.os == 'Linux' && env.STATUS == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} | ||||
|         uses: cpina/github-action-push-to-another-repository@main | ||||
|         env: | ||||
|           SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} | ||||
| @@ -54,7 +57,8 @@ jobs: | ||||
|           target-branch: main | ||||
|           target-directory: v7/core | ||||
|       - name: Publish bukkit javadoc | ||||
|       #  if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} | ||||
|        # if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} | ||||
|         if: ${{ runner.os == 'Linux' && env.STATUS == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} | ||||
|         uses: cpina/github-action-push-to-another-repository@main | ||||
|         env: | ||||
|           SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} | ||||
|   | ||||
							
								
								
									
										15
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,10 +1,11 @@ | ||||
| name: "CodeQL" | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: [ main ] | ||||
|     branches: [ v7 ] | ||||
|   pull_request: | ||||
|     # The branches below must be a subset of the branches above | ||||
|     branches: [ main ] | ||||
|     branches: [ v7 ] | ||||
|  | ||||
| jobs: | ||||
|   analyze: | ||||
| @@ -14,23 +15,23 @@ jobs: | ||||
|       actions: read | ||||
|       contents: read | ||||
|       security-events: write | ||||
|  | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         language: [ 'java' ] | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v3 | ||||
|       - name: Setup Java | ||||
|         uses: actions/setup-java@v3 | ||||
|         with: | ||||
|           distribution: temurin | ||||
|           java-version: 17 | ||||
|  | ||||
|       - name: Initialize CodeQL | ||||
|         uses: github/codeql-action/init@v2 | ||||
|         with: | ||||
|           languages: ${{ matrix.language }} | ||||
|  | ||||
|       - name: Autobuild | ||||
|         uses: github/codeql-action/autobuild@v2 | ||||
|  | ||||
|       - name: Perform CodeQL Analysis | ||||
|         uses: github/codeql-action/analyze@v2 | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/workflows/release-drafter.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/release-drafter.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,12 +1,14 @@ | ||||
| name: draft release | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - main | ||||
|       - v6 | ||||
|   pull_request: | ||||
|     types: [ opened, reopened, synchronize ] | ||||
|   pull_request_target: | ||||
|     types: [ opened, reopened, synchronize ] | ||||
|  | ||||
| jobs: | ||||
|   update_release_draft: | ||||
|     if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} | ||||
|   | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -137,7 +137,3 @@ docs/ | ||||
| build/ | ||||
|  | ||||
| .DS_Store | ||||
| # Ignore run folders | ||||
| run-[0-0].[0-9]/ | ||||
| run-[0-0].[0-9].[0-9]/ | ||||
|  | ||||
|   | ||||
							
								
								
									
										154
									
								
								.idea/icon.svg
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										154
									
								
								.idea/icon.svg
									
									
									
										generated
									
									
									
								
							| @@ -1,144 +1,48 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    version="1.1" | ||||
|    id="svg2" | ||||
|    xml:space="preserve" | ||||
|    width="512" | ||||
|    height="512" | ||||
|    viewBox="0 0 512 512.00001" | ||||
|    sodipodi:docname="icon.svg" | ||||
|    inkscape:version="1.1.2 (b8e25be8, 2022-02-05)" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/"> | ||||
| 		<metadata | ||||
|    id="metadata8"> | ||||
| <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" id="svg2" xml:space="preserve" width="4000" height="3333.3333" viewBox="0 0 4000 3333.3333" sodipodi:docname="PlotSquared.ai"> | ||||
| 		<metadata id="metadata8"> | ||||
| 			<rdf:RDF> | ||||
| 				<cc:Work | ||||
|    rdf:about=""> | ||||
| 				<cc:Work rdf:about=""> | ||||
| 					<dc:format>image/svg+xml</dc:format> | ||||
|                     <dc:type | ||||
|    rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|                     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
| 				</cc:Work> | ||||
| 			</rdf:RDF> | ||||
| 		</metadata> | ||||
|     <defs | ||||
|    id="defs6"> | ||||
| 			<clipPath | ||||
|    clipPathUnits="userSpaceOnUse" | ||||
|    id="clipPath18"> | ||||
| 				<path | ||||
|    d="M 0,2500 H 3000 V 0 H 0 Z" | ||||
|    id="path16" /> | ||||
|     <defs id="defs6"> | ||||
| 			<clipPath clipPathUnits="userSpaceOnUse" id="clipPath18"> | ||||
| 				<path d="M 0,2500 H 3000 V 0 H 0 Z" id="path16" /> | ||||
| 			</clipPath> | ||||
| 		</defs> | ||||
|     <sodipodi:namedview | ||||
|    pagecolor="#ffffff" | ||||
|    bordercolor="#666666" | ||||
|    borderopacity="1" | ||||
|    objecttolerance="10" | ||||
|    gridtolerance="10" | ||||
|    guidetolerance="10" | ||||
|    inkscape:pageopacity="0" | ||||
|    inkscape:pageshadow="2" | ||||
|    inkscape:window-width="1440" | ||||
|    inkscape:window-height="900" | ||||
|    id="namedview4" | ||||
|    inkscape:pagecheckerboard="0" | ||||
|    showgrid="false" | ||||
|    inkscape:zoom="0.1632" | ||||
|    inkscape:cx="1087.6225" | ||||
|    inkscape:cy="1666.6666" | ||||
|    inkscape:window-x="0" | ||||
|    inkscape:window-y="0" | ||||
|    inkscape:window-maximized="0" | ||||
|    inkscape:current-layer="g10" /> | ||||
|     <g | ||||
|    id="g10" | ||||
|    inkscape:groupmode="layer" | ||||
|    inkscape:label="PlotSquared" | ||||
|    transform="matrix(1.3333333,0,0,-1.3333333,0,3333.3333)"> | ||||
| 			<g | ||||
|    id="g12" | ||||
|    transform="matrix(0.16955078,0,0,0.16955078,-68.456969,2101.8529)"> | ||||
| 				<g | ||||
|    id="g14" | ||||
|    clip-path="url(#clipPath18)"> | ||||
| 					<g | ||||
|    id="g20" | ||||
|    transform="translate(1486.1511,2242.6453)"> | ||||
| 						<path | ||||
|    d="m 0,0 c 16.533,10.846 33.211,21.453 50.104,31.699 78.972,-48.281 153.985,-102.704 227.269,-159.144 148.61,-115.422 287.884,-243.01 414.393,-382.333 111.39,-122.861 212.751,-255.152 298.898,-396.971 52.744,-87.322 100.544,-177.884 139.514,-272.214 -11.638,-3.551 -23.108,-7.655 -34.362,-12.286 l -0.24,0.288 c -11.135,12.982 -24.141,24.212 -34.915,37.506 -22.557,23.013 -45.425,45.737 -68.03,68.678 -19.725,20.253 -40.601,39.45 -58.958,60.974 -36.355,36.451 -72.517,73.093 -108.944,109.471 -22.628,26.013 -48.064,49.385 -71.965,74.197 -19.029,19.485 -38.706,38.346 -57.519,57.999 -12.166,14.998 -26.684,27.716 -39.93,41.658 -27.668,27.524 -54.903,55.479 -82.571,82.979 -23.924,27.956 -51.664,52.264 -76.692,79.164 -4.68,4.487 -8.855,10.774 -15.886,11.326 -22.34,34.027 -58.311,57.327 -97.377,67.502 -104.312,99.153 -215.487,191.202 -332.661,274.782 -117.942,-83.94 -229.476,-176.781 -334.484,-276.39 -26.684,-0.024 -53.368,0.024 -80.076,-0.024 0.024,-26.564 0.048,-53.104 0,-79.668 -72.229,-73.021 -139.491,-150.937 -202.385,-232.092 -63.758,-82.619 -121.973,-169.51 -173.541,-260.264 131.932,-69.061 257.864,-149.521 375.926,-240.275 0.096,-26.444 -0.12,-52.888 0.096,-79.332 l 0.744,-0.984 c 20.109,-24.14 43.409,-45.233 65.126,-67.861 15.118,-15.382 30.571,-30.404 45.569,-45.881 17.565,-20.733 37.698,-39.042 56.607,-58.503 19.917,-20.781 41.25,-40.218 59.967,-62.151 29.156,-29.299 58.167,-58.815 87.515,-87.922 29.155,-33.043 61.502,-63.111 92.169,-94.738 13.726,-12.67 25.124,-27.571 38.634,-40.457 25.029,-25.365 50.129,-50.657 75.325,-75.853 -37.914,-51.208 -73.741,-103.952 -107.192,-158.183 -167.83,273.317 -397.235,507.305 -662.37,687.158 -81.875,55.335 -167.23,105.584 -255.681,149.641 -52.815,26.276 -106.831,50.248 -162.239,70.381 99.393,233.628 242.795,446.715 410.289,636.79 93.562,106.088 194.634,205.433 301.466,298.13 C -217.335,-155.808 -111.439,-73.789 0,0" | ||||
|    style="fill:#062f4c;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path22" /> | ||||
|     <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="640" inkscape:window-height="480" id="namedview4" /> | ||||
|     <g id="g10" inkscape:groupmode="layer" inkscape:label="PlotSquared" transform="matrix(1.3333333,0,0,-1.3333333,0,3333.3333)"> | ||||
| 			<g id="g12"> | ||||
| 				<g id="g14" clip-path="url(#clipPath18)"> | ||||
| 					<g id="g20" transform="translate(1486.1511,2242.6453)"> | ||||
| 						<path d="m 0,0 c 16.533,10.846 33.211,21.453 50.104,31.699 78.972,-48.281 153.985,-102.704 227.269,-159.144 148.61,-115.422 287.884,-243.01 414.393,-382.333 111.39,-122.861 212.751,-255.152 298.898,-396.971 52.744,-87.322 100.544,-177.884 139.514,-272.214 -11.638,-3.551 -23.108,-7.655 -34.362,-12.286 l -0.24,0.288 c -11.135,12.982 -24.141,24.212 -34.915,37.506 -22.557,23.013 -45.425,45.737 -68.03,68.678 -19.725,20.253 -40.601,39.45 -58.958,60.974 -36.355,36.451 -72.517,73.093 -108.944,109.471 -22.628,26.013 -48.064,49.385 -71.965,74.197 -19.029,19.485 -38.706,38.346 -57.519,57.999 -12.166,14.998 -26.684,27.716 -39.93,41.658 -27.668,27.524 -54.903,55.479 -82.571,82.979 -23.924,27.956 -51.664,52.264 -76.692,79.164 -4.68,4.487 -8.855,10.774 -15.886,11.326 -22.34,34.027 -58.311,57.327 -97.377,67.502 -104.312,99.153 -215.487,191.202 -332.661,274.782 -117.942,-83.94 -229.476,-176.781 -334.484,-276.39 -26.684,-0.024 -53.368,0.024 -80.076,-0.024 0.024,-26.564 0.048,-53.104 0,-79.668 -72.229,-73.021 -139.491,-150.937 -202.385,-232.092 -63.758,-82.619 -121.973,-169.51 -173.541,-260.264 131.932,-69.061 257.864,-149.521 375.926,-240.275 0.096,-26.444 -0.12,-52.888 0.096,-79.332 l 0.744,-0.984 c 20.109,-24.14 43.409,-45.233 65.126,-67.861 15.118,-15.382 30.571,-30.404 45.569,-45.881 17.565,-20.733 37.698,-39.042 56.607,-58.503 19.917,-20.781 41.25,-40.218 59.967,-62.151 29.156,-29.299 58.167,-58.815 87.515,-87.922 29.155,-33.043 61.502,-63.111 92.169,-94.738 13.726,-12.67 25.124,-27.571 38.634,-40.457 25.029,-25.365 50.129,-50.657 75.325,-75.853 -37.914,-51.208 -73.741,-103.952 -107.192,-158.183 -167.83,273.317 -397.235,507.305 -662.37,687.158 -81.875,55.335 -167.23,105.584 -255.681,149.641 -52.815,26.276 -106.831,50.248 -162.239,70.381 99.393,233.628 242.795,446.715 410.289,636.79 93.562,106.088 194.634,205.433 301.466,298.13 C -217.335,-155.808 -111.439,-73.789 0,0" style="fill:#062f4c;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path22" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g24" | ||||
|    transform="translate(1201.7948,1741.5303)"> | ||||
| 						<path | ||||
|    d="M 0,0 C 105.008,99.609 216.543,192.45 334.485,276.39 451.659,192.81 562.833,100.76 667.146,1.608 c -34.987,8.83 -71.51,9.718 -107.264,6.431 -41.202,-4.296 -82.907,-19.077 -112.543,-48.953 -33.019,-32.155 -49.456,-77.604 -55.311,-122.501 -28.124,27.908 -56.104,55.983 -84.035,84.083 -2.976,2.976 -6.839,4.823 -10.391,6.911 -19.029,26.348 -45.953,46.673 -76.62,57.495 C 187.555,-2.472 151.513,-0.12 116.166,0 Z" | ||||
|    style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path26" /> | ||||
|                     <g id="g24" transform="translate(1201.7948,1741.5303)"> | ||||
| 						<path d="M 0,0 C 105.008,99.609 216.543,192.45 334.485,276.39 451.659,192.81 562.833,100.76 667.146,1.608 c -34.987,8.83 -71.51,9.718 -107.264,6.431 -41.202,-4.296 -82.907,-19.077 -112.543,-48.953 -33.019,-32.155 -49.456,-77.604 -55.311,-122.501 -28.124,27.908 -56.104,55.983 -84.035,84.083 -2.976,2.976 -6.839,4.823 -10.391,6.911 -19.029,26.348 -45.953,46.673 -76.62,57.495 C 187.555,-2.472 151.513,-0.12 116.166,0 Z" style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path26" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g28" | ||||
|    transform="translate(919.3342,1429.7462)"> | ||||
| 						<path | ||||
|    d="m 0,0 c 62.894,81.156 130.156,159.072 202.385,232.092 0.048,-244.21 0.024,-488.421 0,-732.631 C 84.323,-409.785 -41.61,-329.325 -173.541,-260.264 -121.973,-169.51 -63.758,-82.619 0,0" | ||||
|    style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path30" /> | ||||
|                     <g id="g28" transform="translate(919.3342,1429.7462)"> | ||||
| 						<path d="m 0,0 c 62.894,81.156 130.156,159.072 202.385,232.092 0.048,-244.21 0.024,-488.421 0,-732.631 C 84.323,-409.785 -41.61,-329.325 -173.541,-260.264 -121.973,-169.51 -63.758,-82.619 0,0" style="fill:#4c8fcc;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path30" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g32" | ||||
|    transform="translate(1649.134,1700.6166)"> | ||||
| 						<path | ||||
|    d="m 0,0 c 29.635,29.875 71.341,44.657 112.543,48.952 35.754,3.288 72.277,2.4 107.263,-6.431 39.066,-10.174 75.037,-33.474 97.377,-67.501 11.879,-17.661 20.181,-37.411 26.42,-57.687 10.871,-38.802 11.95,-79.356 11.446,-119.358 -44.345,-0.072 -88.69,0.048 -133.035,-0.072 -1.032,30.907 3.263,63.686 -10.175,92.626 -9.526,20.325 -32.107,31.243 -53.751,32.131 -21.453,1.44 -45.065,-4.32 -59.175,-21.597 -12.79,-15.861 -15.382,-37.002 -16.558,-56.655 -1.295,-29.132 3.696,-59.031 17.518,-84.923 16.821,-30.619 39.378,-57.783 64.526,-81.9 31.387,-32.634 67.501,-60.374 97.857,-94.041 27.332,-28.988 51.256,-61.479 68.005,-97.785 20.541,-41.13 26.972,-87.827 25.82,-133.372 -0.912,-32.107 -5.231,-64.406 -16.149,-94.737 -11.59,-31.699 -31.123,-61.047 -58.335,-81.371 -25.124,-19.125 -55.696,-29.852 -86.651,-34.771 -49.552,-6.743 -101.888,-4.847 -148.465,14.854 -35.227,14.829 -64.238,42.689 -81.708,76.548 -20.996,40.242 -27.115,86.339 -27.259,131.212 0.048,17.829 0,35.658 0.048,53.463 44.345,0.048 88.69,-0.023 133.059,0.048 1.728,-35.538 -4.055,-72.06 5.663,-106.807 5.783,-22.173 26.204,-37.794 48.185,-41.754 20.733,-3.431 43.577,-2.015 61.622,9.791 15.502,9.43 23.949,26.78 26.78,44.225 5.903,35.922 1.872,74.293 -15.381,106.688 -16.918,30.595 -39.474,57.711 -64.55,81.899 -33.187,34.099 -71.173,63.254 -102.585,99.081 -26.756,28.867 -49.408,61.646 -65.486,97.641 -24.572,52.48 -26.731,112.422 -20.18,169.102 C -49.456,-77.604 -33.019,-32.155 0,0" | ||||
|    style="fill:#feeeee;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path34" /> | ||||
|                     <g id="g32" transform="translate(1649.134,1700.6166)"> | ||||
| 						<path d="m 0,0 c 29.635,29.875 71.341,44.657 112.543,48.952 35.754,3.288 72.277,2.4 107.263,-6.431 39.066,-10.174 75.037,-33.474 97.377,-67.501 11.879,-17.661 20.181,-37.411 26.42,-57.687 10.871,-38.802 11.95,-79.356 11.446,-119.358 -44.345,-0.072 -88.69,0.048 -133.035,-0.072 -1.032,30.907 3.263,63.686 -10.175,92.626 -9.526,20.325 -32.107,31.243 -53.751,32.131 -21.453,1.44 -45.065,-4.32 -59.175,-21.597 -12.79,-15.861 -15.382,-37.002 -16.558,-56.655 -1.295,-29.132 3.696,-59.031 17.518,-84.923 16.821,-30.619 39.378,-57.783 64.526,-81.9 31.387,-32.634 67.501,-60.374 97.857,-94.041 27.332,-28.988 51.256,-61.479 68.005,-97.785 20.541,-41.13 26.972,-87.827 25.82,-133.372 -0.912,-32.107 -5.231,-64.406 -16.149,-94.737 -11.59,-31.699 -31.123,-61.047 -58.335,-81.371 -25.124,-19.125 -55.696,-29.852 -86.651,-34.771 -49.552,-6.743 -101.888,-4.847 -148.465,14.854 -35.227,14.829 -64.238,42.689 -81.708,76.548 -20.996,40.242 -27.115,86.339 -27.259,131.212 0.048,17.829 0,35.658 0.048,53.463 44.345,0.048 88.69,-0.023 133.059,0.048 1.728,-35.538 -4.055,-72.06 5.663,-106.807 5.783,-22.173 26.204,-37.794 48.185,-41.754 20.733,-3.431 43.577,-2.015 61.622,9.791 15.502,9.43 23.949,26.78 26.78,44.225 5.903,35.922 1.872,74.293 -15.381,106.688 -16.918,30.595 -39.474,57.711 -64.55,81.899 -33.187,34.099 -71.173,63.254 -102.585,99.081 -26.756,28.867 -49.408,61.646 -65.486,97.641 -24.572,52.48 -26.731,112.422 -20.18,169.102 C -49.456,-77.604 -33.019,-32.155 0,0" style="fill:#feeeee;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path34" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g36" | ||||
|    transform="translate(1262.7214,1613.126)"> | ||||
| 						<path | ||||
|    d="m 0,0 v -301.13 c 23.204,0.024 46.409,-0.048 69.613,0.024 18.525,0.288 38.202,6.575 50.153,21.429 12.43,17.277 13.917,39.522 14.613,60.111 0.024,43.985 -0.048,87.994 0.024,131.979 -0.48,23.637 -0.983,50.369 -17.277,69.23 C 104.864,-5.711 86.867,-0.24 69.589,0 46.385,0.048 23.204,0.024 0,0 m -141.002,128.38 c 26.708,0.048 53.392,0 80.075,0.024 H 55.24 c 35.346,-0.12 71.389,-2.471 104.815,-14.925 30.668,-10.823 57.592,-31.148 76.621,-57.496 26.852,-39.09 36.69,-87.202 38.058,-133.947 0.024,-48.833 0.096,-97.689 -0.024,-146.521 -1.728,-47.993 -11.974,-97.953 -41.514,-136.971 -22.748,-30.644 -57.495,-50.801 -94.281,-59.583 -45.377,-11.878 -92.578,-6.791 -138.891,-7.847 -0.072,-111.799 0,-223.574 -0.024,-335.373 -13.942,0 -27.86,0.024 -41.778,-0.024 -32.802,0.072 -65.605,0 -98.384,0.048 l -0.744,0.984 c -0.216,26.444 0,52.888 -0.096,79.332 0.024,244.211 0.048,488.421 0,732.632 0.048,26.563 0.024,53.103 0,79.667" | ||||
|    style="fill:#feeeee;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path38" /> | ||||
|                     <g id="g36" transform="translate(1262.7214,1613.126)"> | ||||
| 						<path d="m 0,0 v -301.13 c 23.204,0.024 46.409,-0.048 69.613,0.024 18.525,0.288 38.202,6.575 50.153,21.429 12.43,17.277 13.917,39.522 14.613,60.111 0.024,43.985 -0.048,87.994 0.024,131.979 -0.48,23.637 -0.983,50.369 -17.277,69.23 C 104.864,-5.711 86.867,-0.24 69.589,0 46.385,0.048 23.204,0.024 0,0 m -141.002,128.38 c 26.708,0.048 53.392,0 80.075,0.024 H 55.24 c 35.346,-0.12 71.389,-2.471 104.815,-14.925 30.668,-10.823 57.592,-31.148 76.621,-57.496 26.852,-39.09 36.69,-87.202 38.058,-133.947 0.024,-48.833 0.096,-97.689 -0.024,-146.521 -1.728,-47.993 -11.974,-97.953 -41.514,-136.971 -22.748,-30.644 -57.495,-50.801 -94.281,-59.583 -45.377,-11.878 -92.578,-6.791 -138.891,-7.847 -0.072,-111.799 0,-223.574 -0.024,-335.373 -13.942,0 -27.86,0.024 -41.778,-0.024 -32.802,0.072 -65.605,0 -98.384,0.048 l -0.744,0.984 c -0.216,26.444 0,52.888 -0.096,79.332 0.024,244.211 0.048,488.421 0,732.632 0.048,26.563 0.024,53.103 0,79.667" style="fill:#feeeee;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path38" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g40" | ||||
|    transform="translate(1966.3174,1675.6364)"> | ||||
| 						<path | ||||
|    d="m 0,0 c 7.031,-0.552 11.206,-6.839 15.885,-11.326 25.029,-26.9 52.768,-51.208 76.693,-79.164 27.667,-27.5 54.903,-55.456 82.571,-82.979 13.246,-13.942 27.764,-26.66 39.93,-41.658 18.813,-19.653 38.49,-38.514 57.519,-57.999 23.9,-24.812 49.337,-48.185 71.965,-74.197 36.427,-36.378 72.589,-73.02 108.943,-109.471 18.358,-21.524 39.234,-40.722 58.959,-60.974 22.605,-22.941 45.473,-45.665 68.03,-68.678 10.774,-13.294 23.78,-24.524 34.914,-37.506 -103.904,-41.97 -203.488,-94.114 -298.922,-152.761 -246.994,-152.28 -466.224,-350.298 -639.333,-583.398 -25.197,25.196 -50.297,50.488 -75.325,75.852 -13.51,12.886 -24.908,27.788 -38.634,40.458 -30.667,31.627 -63.014,61.695 -92.17,94.738 -29.347,29.107 -58.359,58.623 -87.514,87.922 -18.717,21.933 -40.05,41.37 -59.967,62.151 -18.909,19.461 -39.042,37.77 -56.607,58.503 -14.998,15.477 -30.452,30.499 -45.569,45.88 -21.717,22.629 -45.017,43.722 -65.126,67.862 32.779,-0.048 65.582,0.024 98.384,-0.048 114.391,-98.097 220.407,-205.984 315.384,-322.99 92.914,114.318 196.242,220.022 307.753,316.271 30.955,4.919 61.526,15.646 86.65,34.771 27.212,20.325 46.745,49.672 58.335,81.371 107.312,77.988 219.327,149.929 337.509,210.376 -35.299,64.67 -75.829,126.437 -118.254,186.643 C 176.253,-228.037 104.24,-140.115 26.42,-57.687 20.181,-37.41 11.878,-17.661 0,0" | ||||
|    style="fill:#042338;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path42" /> | ||||
|                     <g id="g40" transform="translate(1966.3174,1675.6364)"> | ||||
| 						<path d="m 0,0 c 7.031,-0.552 11.206,-6.839 15.885,-11.326 25.029,-26.9 52.768,-51.208 76.693,-79.164 27.667,-27.5 54.903,-55.456 82.571,-82.979 13.246,-13.942 27.764,-26.66 39.93,-41.658 18.813,-19.653 38.49,-38.514 57.519,-57.999 23.9,-24.812 49.337,-48.185 71.965,-74.197 36.427,-36.378 72.589,-73.02 108.943,-109.471 18.358,-21.524 39.234,-40.722 58.959,-60.974 22.605,-22.941 45.473,-45.665 68.03,-68.678 10.774,-13.294 23.78,-24.524 34.914,-37.506 -103.904,-41.97 -203.488,-94.114 -298.922,-152.761 -246.994,-152.28 -466.224,-350.298 -639.333,-583.398 -25.197,25.196 -50.297,50.488 -75.325,75.852 -13.51,12.886 -24.908,27.788 -38.634,40.458 -30.667,31.627 -63.014,61.695 -92.17,94.738 -29.347,29.107 -58.359,58.623 -87.514,87.922 -18.717,21.933 -40.05,41.37 -59.967,62.151 -18.909,19.461 -39.042,37.77 -56.607,58.503 -14.998,15.477 -30.452,30.499 -45.569,45.88 -21.717,22.629 -45.017,43.722 -65.126,67.862 32.779,-0.048 65.582,0.024 98.384,-0.048 114.391,-98.097 220.407,-205.984 315.384,-322.99 92.914,114.318 196.242,220.022 307.753,316.271 30.955,4.919 61.526,15.646 86.65,34.771 27.212,20.325 46.745,49.672 58.335,81.371 107.312,77.988 219.327,149.929 337.509,210.376 -35.299,64.67 -75.829,126.437 -118.254,186.643 C 176.253,-228.037 104.24,-140.115 26.42,-57.687 20.181,-37.41 11.878,-17.661 0,0" style="fill:#042338;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path42" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g44" | ||||
|    transform="translate(1499.3971,1669.1094)"> | ||||
| 						<path | ||||
|    d="m 0,0 c 3.551,-2.088 7.415,-3.935 10.39,-6.911 27.932,-28.1 55.912,-56.175 84.036,-84.083 -6.551,-56.679 -4.392,-116.622 20.18,-169.102 16.078,-35.994 38.73,-68.774 65.486,-97.641 31.412,-35.826 69.398,-64.982 102.585,-99.081 25.076,-24.188 47.632,-51.304 64.55,-81.899 17.253,-32.395 21.284,-70.765 15.381,-106.688 -2.831,-17.445 -11.278,-34.794 -26.78,-44.225 -18.045,-11.806 -40.889,-13.222 -61.622,-9.79 -21.981,3.959 -42.402,19.58 -48.185,41.753 -9.718,34.747 -3.935,71.269 -5.663,106.808 -44.369,-0.072 -88.714,0 -133.059,-0.048 -0.048,-17.806 0,-35.635 -0.048,-53.464 0.144,-44.873 6.263,-90.97 27.259,-131.212 17.47,-33.859 46.481,-61.718 81.708,-76.548 46.577,-19.701 98.913,-21.597 148.465,-14.854 -111.511,-96.249 -214.839,-201.953 -307.753,-316.271 -94.977,117.006 -200.993,224.893 -315.383,322.99 13.918,0.048 27.836,0.024 41.777,0.024 0.024,111.799 -0.048,223.574 0.024,335.372 46.313,1.056 93.514,-4.031 138.891,7.847 36.786,8.783 71.533,28.94 94.282,59.583 29.539,39.018 39.785,88.978 41.513,136.971 0.12,48.833 0.048,97.689 0.024,146.522 C 36.69,-87.203 26.852,-39.09 0,0" | ||||
|    style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path46" /> | ||||
|                     <g id="g44" transform="translate(1499.3971,1669.1094)"> | ||||
| 						<path d="m 0,0 c 3.551,-2.088 7.415,-3.935 10.39,-6.911 27.932,-28.1 55.912,-56.175 84.036,-84.083 -6.551,-56.679 -4.392,-116.622 20.18,-169.102 16.078,-35.994 38.73,-68.774 65.486,-97.641 31.412,-35.826 69.398,-64.982 102.585,-99.081 25.076,-24.188 47.632,-51.304 64.55,-81.899 17.253,-32.395 21.284,-70.765 15.381,-106.688 -2.831,-17.445 -11.278,-34.794 -26.78,-44.225 -18.045,-11.806 -40.889,-13.222 -61.622,-9.79 -21.981,3.959 -42.402,19.58 -48.185,41.753 -9.718,34.747 -3.935,71.269 -5.663,106.808 -44.369,-0.072 -88.714,0 -133.059,-0.048 -0.048,-17.806 0,-35.635 -0.048,-53.464 0.144,-44.873 6.263,-90.97 27.259,-131.212 17.47,-33.859 46.481,-61.718 81.708,-76.548 46.577,-19.701 98.913,-21.597 148.465,-14.854 -111.511,-96.249 -214.839,-201.953 -307.753,-316.271 -94.977,117.006 -200.993,224.893 -315.383,322.99 13.918,0.048 27.836,0.024 41.777,0.024 0.024,111.799 -0.048,223.574 0.024,335.372 46.313,1.056 93.514,-4.031 138.891,7.847 36.786,8.783 71.533,28.94 94.282,59.583 29.539,39.018 39.785,88.978 41.513,136.971 0.12,48.833 0.048,97.689 0.024,146.522 C 36.69,-87.203 26.852,-39.09 0,0" style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path46" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g48" | ||||
|    transform="translate(1748.0469,1601.6797)"> | ||||
| 						<path | ||||
|    d="M 0,0 C 14.11,17.277 37.722,23.036 59.175,21.597 80.82,20.709 103.4,9.791 112.927,-10.534 c 13.438,-28.94 9.142,-61.719 10.174,-92.626 44.345,0.12 88.691,0 133.036,0.072 0.504,40.002 -0.576,80.556 -11.447,119.358 77.82,-82.428 149.833,-170.35 215.583,-262.664 42.426,-60.207 82.956,-121.973 118.254,-186.643 -118.182,-60.447 -230.196,-132.388 -337.508,-210.376 10.918,30.331 15.238,62.63 16.149,94.737 1.152,45.545 -5.279,92.242 -25.82,133.372 -16.749,36.306 -40.673,68.797 -68.005,97.785 -30.355,33.667 -66.47,61.406 -97.857,94.041 -25.148,24.117 -47.705,51.28 -64.526,81.9 -13.822,25.892 -18.813,55.791 -17.517,84.923 C -15.382,-37.002 -12.79,-15.862 0,0" | ||||
|    style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path50" /> | ||||
|                     <g id="g48" transform="translate(1748.0469,1601.6797)"> | ||||
| 						<path d="M 0,0 C 14.11,17.277 37.722,23.036 59.175,21.597 80.82,20.709 103.4,9.791 112.927,-10.534 c 13.438,-28.94 9.142,-61.719 10.174,-92.626 44.345,0.12 88.691,0 133.036,0.072 0.504,40.002 -0.576,80.556 -11.447,119.358 77.82,-82.428 149.833,-170.35 215.583,-262.664 42.426,-60.207 82.956,-121.973 118.254,-186.643 -118.182,-60.447 -230.196,-132.388 -337.508,-210.376 10.918,30.331 15.238,62.63 16.149,94.737 1.152,45.545 -5.279,92.242 -25.82,133.372 -16.749,36.306 -40.673,68.797 -68.005,97.785 -30.355,33.667 -66.47,61.406 -97.857,94.041 -25.148,24.117 -47.705,51.28 -64.526,81.9 -13.822,25.892 -18.813,55.791 -17.517,84.923 C -15.382,-37.002 -12.79,-15.862 0,0" style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path50" /> | ||||
| 					</g> | ||||
|                     <g | ||||
|    id="g52" | ||||
|    transform="translate(1262.7214,1613.126)"> | ||||
| 						<path | ||||
|    d="m 0,0 c 23.204,0.024 46.385,0.048 69.589,0 17.278,-0.24 35.275,-5.711 47.537,-18.357 16.294,-18.861 16.797,-45.593 17.277,-69.23 -0.072,-43.985 0,-87.994 -0.024,-131.979 -0.696,-20.589 -2.183,-42.834 -14.613,-60.111 -11.951,-14.854 -31.628,-21.141 -50.153,-21.429 -23.204,-0.072 -46.409,0 -69.613,-0.024 z" | ||||
|    style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" | ||||
|    id="path54" /> | ||||
|                     <g id="g52" transform="translate(1262.7214,1613.126)"> | ||||
| 						<path d="m 0,0 c 23.204,0.024 46.385,0.048 69.589,0 17.278,-0.24 35.275,-5.711 47.537,-18.357 16.294,-18.861 16.797,-45.593 17.277,-69.23 -0.072,-43.985 0,-87.994 -0.024,-131.979 -0.696,-20.589 -2.183,-42.834 -14.613,-60.111 -11.951,-14.854 -31.628,-21.141 -50.153,-21.429 -23.204,-0.072 -46.409,0 -69.613,-0.024 z" style="fill:#1c72ba;fill-opacity:1;fill-rule:nonzero;stroke:none" id="path54" /> | ||||
| 					</g> | ||||
| 				</g> | ||||
| 			</g> | ||||
|   | ||||
| Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB | 
| @@ -18,7 +18,7 @@ repositories { | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
|     api(projects.plotsquaredCore) | ||||
|     api(projects.plotSquaredCore) | ||||
|  | ||||
|     // Metrics | ||||
|     implementation("org.bstats:bstats-bukkit") | ||||
| @@ -53,6 +53,10 @@ dependencies { | ||||
|  | ||||
|     // Adventure | ||||
|     implementation("net.kyori:adventure-platform-bukkit") | ||||
|  | ||||
|     // Cloud | ||||
|     implementation(libs.cloudPaper) | ||||
|     implementation(libs.cloudMinecraftExtras) | ||||
| } | ||||
|  | ||||
| tasks.processResources { | ||||
| @@ -62,7 +66,6 @@ tasks.processResources { | ||||
| } | ||||
|  | ||||
| tasks.named<ShadowJar>("shadowJar") { | ||||
|     dependsOn(":plotsquared-core:shadowJar") | ||||
|     dependencies { | ||||
|         exclude(dependency("org.checkerframework:")) | ||||
|     } | ||||
| @@ -103,7 +106,7 @@ tasks { | ||||
|         opt.links("https://jd.papermc.io/paper/1.19/") | ||||
|         opt.links("https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-bukkit/" + libs.worldeditBukkit.get().versionConstraint.toString()) | ||||
|         opt.links("https://intellectualsites.github.io/plotsquared-javadocs/core/") | ||||
|         opt.links("https://jd.advntr.dev/api/4.14.0/") | ||||
|         opt.links("https://jd.adventure.kyori.net/api/4.12.0/") | ||||
|         opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/") | ||||
|         opt.links("https://checkerframework.org/api/") | ||||
|         opt.isLinkSource = true | ||||
|   | ||||
| @@ -49,6 +49,7 @@ import com.plotsquared.bukkit.player.BukkitPlayerManager; | ||||
| import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.plotsquared.bukkit.util.BukkitWorld; | ||||
| import com.plotsquared.bukkit.util.SetGenCB; | ||||
| import com.plotsquared.bukkit.util.UpdateUtility; | ||||
| import com.plotsquared.bukkit.util.TranslationUpdateManager; | ||||
| import com.plotsquared.bukkit.util.task.BukkitTaskManager; | ||||
| import com.plotsquared.bukkit.util.task.PaperTimeConverter; | ||||
| @@ -62,6 +63,7 @@ import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; | ||||
| import com.plotsquared.core.PlotPlatform; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.backup.BackupManager; | ||||
| import com.plotsquared.core.commands.PlotSquaredCommandManager; | ||||
| import com.plotsquared.core.components.ComponentPresetManager; | ||||
| import com.plotsquared.core.configuration.ConfigurationNode; | ||||
| import com.plotsquared.core.configuration.ConfigurationSection; | ||||
| @@ -214,6 +216,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|     @Inject | ||||
|     private PlatformWorldManager<World> worldManager; | ||||
|     private Locale serverLocale; | ||||
|     @Inject | ||||
|     private PlotSquaredCommandManager commandManager; | ||||
|  | ||||
|     @SuppressWarnings("StringSplitter") | ||||
|     @Override | ||||
| @@ -302,11 +306,9 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|  | ||||
|         this.serverLocale = Locale.forLanguageTag(Settings.Enabled_Components.DEFAULT_LOCALE); | ||||
|  | ||||
|         /* TODO Enable update checker before v7 is released to GA | ||||
|         if (PremiumVerification.isPremium() && Settings.Enabled_Components.UPDATE_NOTIFICATIONS) { | ||||
|             injector.getInstance(UpdateUtility.class).updateChecker(); | ||||
|         } | ||||
|          */ | ||||
|  | ||||
|         if (PremiumVerification.isPremium()) { | ||||
|             LOGGER.info("PlotSquared version licensed to Spigot user {}", getUserID()); | ||||
| @@ -367,7 +369,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|             getServer().getPluginManager().registerEvents(injector().getInstance(ServerListener.class), this); | ||||
|             getServer().getPluginManager().registerEvents(injector().getInstance(EntitySpawnListener.class), this); | ||||
|             if (PaperLib.isPaper() && Settings.Paper_Components.PAPER_LISTENERS) { | ||||
|                 getServer().getPluginManager().registerEvents(injector().getInstance(PaperListener.class), this); | ||||
|                     getServer().getPluginManager().registerEvents(injector().getInstance(PaperListener.class), this); | ||||
|             } else { | ||||
|                 getServer().getPluginManager().registerEvents(injector().getInstance(SpigotListener.class), this); | ||||
|             } | ||||
| @@ -383,6 +385,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|         // Commands | ||||
|         if (Settings.Enabled_Components.COMMANDS) { | ||||
|             this.registerCommands(); | ||||
|             this.commandManager.initializeCommands(); | ||||
|         } | ||||
|  | ||||
|         // Permissions | ||||
| @@ -1186,17 +1189,9 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|     public @NonNull String worldEditImplementations() { | ||||
|         StringBuilder msg = new StringBuilder(); | ||||
|         if (Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null) { | ||||
|             msg.append("FastAsyncWorldEdit: ").append(Bukkit | ||||
|                     .getPluginManager() | ||||
|                     .getPlugin("FastAsyncWorldEdit") | ||||
|                     .getDescription() | ||||
|                     .getVersion()); | ||||
|             msg.append("FastAsyncWorldEdit: ").append(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit").getDescription().getVersion()); | ||||
|         } else if (Bukkit.getPluginManager().getPlugin("AsyncWorldEdit") != null) { | ||||
|             msg.append("AsyncWorldEdit: ").append(Bukkit | ||||
|                     .getPluginManager() | ||||
|                     .getPlugin("AsyncWorldEdit") | ||||
|                     .getDescription() | ||||
|                     .getVersion()).append("\n"); | ||||
|             msg.append("AsyncWorldEdit: ").append(Bukkit.getPluginManager().getPlugin("AsyncWorldEdit").getDescription().getVersion()).append("\n"); | ||||
|             msg.append("WorldEdit: ").append(Bukkit.getPluginManager().getPlugin("WorldEdit").getDescription().getVersion()); | ||||
|         } else { | ||||
|             msg.append("WorldEdit: ").append(Bukkit.getPluginManager().getPlugin("WorldEdit").getDescription().getVersion()); | ||||
|   | ||||
| @@ -101,26 +101,50 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|             this.noGravity = true; | ||||
|         } | ||||
|         switch (entity.getType().toString()) { | ||||
|             case "BOAT" -> { | ||||
|             case "BOAT": | ||||
|                 Boat boat = (Boat) entity; | ||||
|                 this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); | ||||
|                 return; | ||||
|             } | ||||
|             case "ARROW", "EGG", "ENDER_CRYSTAL", "ENDER_PEARL", "ENDER_SIGNAL", "EXPERIENCE_ORB", "FALLING_BLOCK", "FIREBALL", | ||||
|                     "FIREWORK", "FISHING_HOOK", "LEASH_HITCH", "LIGHTNING", "MINECART", "MINECART_COMMAND", "MINECART_MOB_SPAWNER", | ||||
|                     "MINECART_TNT", "PLAYER", "PRIMED_TNT", "SLIME", "SMALL_FIREBALL", "SNOWBALL", "MINECART_FURNACE", "SPLASH_POTION", | ||||
|                     "THROWN_EXP_BOTTLE", "WITHER_SKULL", "UNKNOWN", "SPECTRAL_ARROW", "SHULKER_BULLET", "DRAGON_FIREBALL", "AREA_EFFECT_CLOUD", | ||||
|                     "TRIDENT", "LLAMA_SPIT" -> { | ||||
|             case "ARROW": | ||||
|             case "EGG": | ||||
|             case "ENDER_CRYSTAL": | ||||
|             case "ENDER_PEARL": | ||||
|             case "ENDER_SIGNAL": | ||||
|             case "EXPERIENCE_ORB": | ||||
|             case "FALLING_BLOCK": | ||||
|             case "FIREBALL": | ||||
|             case "FIREWORK": | ||||
|             case "FISHING_HOOK": | ||||
|             case "LEASH_HITCH": | ||||
|             case "LIGHTNING": | ||||
|             case "MINECART": | ||||
|             case "MINECART_COMMAND": | ||||
|             case "MINECART_MOB_SPAWNER": | ||||
|             case "MINECART_TNT": | ||||
|             case "PLAYER": | ||||
|             case "PRIMED_TNT": | ||||
|             case "SLIME": | ||||
|             case "SMALL_FIREBALL": | ||||
|             case "SNOWBALL": | ||||
|             case "MINECART_FURNACE": | ||||
|             case "SPLASH_POTION": | ||||
|             case "THROWN_EXP_BOTTLE": | ||||
|             case "WITHER_SKULL": | ||||
|             case "UNKNOWN": | ||||
|             case "SPECTRAL_ARROW": | ||||
|             case "SHULKER_BULLET": | ||||
|             case "DRAGON_FIREBALL": | ||||
|             case "AREA_EFFECT_CLOUD": | ||||
|             case "TRIDENT": | ||||
|             case "LLAMA_SPIT": | ||||
|                 // Do this stuff later | ||||
|                 return; | ||||
|             } | ||||
|             // MISC // | ||||
|             case "DROPPED_ITEM" -> { | ||||
|             case "DROPPED_ITEM": | ||||
|                 Item item = (Item) entity; | ||||
|                 this.stack = item.getItemStack(); | ||||
|                 return; | ||||
|             } | ||||
|             case "ITEM_FRAME" -> { | ||||
|             case "ITEM_FRAME": | ||||
|                 this.x = Math.floor(this.getX()); | ||||
|                 this.y = Math.floor(this.getY()); | ||||
|                 this.z = Math.floor(this.getZ()); | ||||
| @@ -128,8 +152,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); | ||||
|                 this.stack = itemFrame.getItem().clone(); | ||||
|                 return; | ||||
|             } | ||||
|             case "PAINTING" -> { | ||||
|             case "PAINTING": | ||||
|                 this.x = Math.floor(this.getX()); | ||||
|                 this.y = Math.floor(this.getY()); | ||||
|                 this.z = Math.floor(this.getZ()); | ||||
| @@ -142,17 +165,20 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 } | ||||
|                 this.dataString = art.name(); | ||||
|                 return; | ||||
|             } | ||||
|             // END MISC // | ||||
|             // INVENTORY HOLDER // | ||||
|             case "MINECART_CHEST", "MINECART_HOPPER" -> { | ||||
|             case "MINECART_CHEST": | ||||
|             case "MINECART_HOPPER": | ||||
|                 storeInventory((InventoryHolder) entity); | ||||
|                 return; | ||||
|             } | ||||
|             // START LIVING ENTITY // | ||||
|             // START AGEABLE // | ||||
|             // START TAMEABLE // | ||||
|             case "HORSE", "DONKEY", "LLAMA", "MULE", "SKELETON_HORSE" -> { | ||||
|             case "HORSE": | ||||
|             case "DONKEY": | ||||
|             case "LLAMA": | ||||
|             case "MULE": | ||||
|             case "SKELETON_HORSE": | ||||
|                 AbstractHorse horse = (AbstractHorse) entity; | ||||
|                 this.horse = new HorseStats(); | ||||
|                 this.horse.jump = horse.getJumpStrength(); | ||||
| @@ -168,17 +194,16 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 storeLiving(horse); | ||||
|                 storeInventory(horse); | ||||
|                 return; | ||||
|             } | ||||
|             // END INVENTORY HOLDER // | ||||
|             case "WOLF", "OCELOT" -> { | ||||
|             case "WOLF": | ||||
|             case "OCELOT": | ||||
|                 storeTameable((Tameable) entity); | ||||
|                 storeAgeable((Ageable) entity); | ||||
|                 storeLiving((LivingEntity) entity); | ||||
|                 return; | ||||
|             } | ||||
|             // END TAMEABLE // | ||||
|             //todo fix sheep | ||||
|             case "SHEEP" -> { | ||||
|             case "SHEEP": | ||||
|                 Sheep sheep = (Sheep) entity; | ||||
|                 if (sheep.isSheared()) { | ||||
|                     this.dataByte = (byte) 1; | ||||
| @@ -189,20 +214,23 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 storeAgeable(sheep); | ||||
|                 storeLiving(sheep); | ||||
|                 return; | ||||
|             } | ||||
|             case "VILLAGER", "CHICKEN", "COW", "MUSHROOM_COW", "PIG", "TURTLE", "POLAR_BEAR" -> { | ||||
|             case "VILLAGER": | ||||
|             case "CHICKEN": | ||||
|             case "COW": | ||||
|             case "MUSHROOM_COW": | ||||
|             case "PIG": | ||||
|             case "TURTLE": | ||||
|             case "POLAR_BEAR": | ||||
|                 storeAgeable((Ageable) entity); | ||||
|                 storeLiving((LivingEntity) entity); | ||||
|                 return; | ||||
|             } | ||||
|             case "RABBIT" -> { | ||||
|             case "RABBIT": | ||||
|                 this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType()); | ||||
|                 storeAgeable((Ageable) entity); | ||||
|                 storeLiving((LivingEntity) entity); | ||||
|                 return; | ||||
|             } | ||||
|             // END AGEABLE // | ||||
|             case "ARMOR_STAND" -> { | ||||
|             case "ARMOR_STAND": | ||||
|                 ArmorStand stand = (ArmorStand) entity; | ||||
|                 this.inventory = | ||||
|                         new ItemStack[]{stand.getItemInHand().clone(), stand.getHelmet().clone(), | ||||
| @@ -210,30 +238,37 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                                 stand.getBoots().clone()}; | ||||
|                 storeLiving(stand); | ||||
|                 this.stand = new ArmorStandStats(); | ||||
|  | ||||
|                 EulerAngle head = stand.getHeadPose(); | ||||
|                 this.stand.head[0] = (float) head.getX(); | ||||
|                 this.stand.head[1] = (float) head.getY(); | ||||
|                 this.stand.head[2] = (float) head.getZ(); | ||||
|  | ||||
|                 EulerAngle body = stand.getBodyPose(); | ||||
|                 this.stand.body[0] = (float) body.getX(); | ||||
|                 this.stand.body[1] = (float) body.getY(); | ||||
|                 this.stand.body[2] = (float) body.getZ(); | ||||
|  | ||||
|                 EulerAngle leftLeg = stand.getLeftLegPose(); | ||||
|                 this.stand.leftLeg[0] = (float) leftLeg.getX(); | ||||
|                 this.stand.leftLeg[1] = (float) leftLeg.getY(); | ||||
|                 this.stand.leftLeg[2] = (float) leftLeg.getZ(); | ||||
|  | ||||
|                 EulerAngle rightLeg = stand.getRightLegPose(); | ||||
|                 this.stand.rightLeg[0] = (float) rightLeg.getX(); | ||||
|                 this.stand.rightLeg[1] = (float) rightLeg.getY(); | ||||
|                 this.stand.rightLeg[2] = (float) rightLeg.getZ(); | ||||
|  | ||||
|                 EulerAngle leftArm = stand.getLeftArmPose(); | ||||
|                 this.stand.leftArm[0] = (float) leftArm.getX(); | ||||
|                 this.stand.leftArm[1] = (float) leftArm.getY(); | ||||
|                 this.stand.leftArm[2] = (float) leftArm.getZ(); | ||||
|  | ||||
|                 EulerAngle rightArm = stand.getRightArmPose(); | ||||
|                 this.stand.rightArm[0] = (float) rightArm.getX(); | ||||
|                 this.stand.rightArm[1] = (float) rightArm.getY(); | ||||
|                 this.stand.rightArm[2] = (float) rightArm.getZ(); | ||||
|  | ||||
|                 if (stand.hasArms()) { | ||||
|                     this.stand.arms = true; | ||||
|                 } | ||||
| @@ -247,38 +282,53 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                     this.stand.small = true; | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             case "ENDERMITE" -> { | ||||
|             case "ENDERMITE": | ||||
|                 return; | ||||
|             } | ||||
|             case "BAT" -> { | ||||
|             case "BAT": | ||||
|                 if (((Bat) entity).isAwake()) { | ||||
|                     this.dataByte = (byte) 1; | ||||
|                 } else { | ||||
|                     this.dataByte = (byte) 0; | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             case "ENDER_DRAGON" -> { | ||||
|             case "ENDER_DRAGON": | ||||
|                 EnderDragon entity1 = (EnderDragon) entity; | ||||
|                 this.dataByte = (byte) entity1.getPhase().ordinal(); | ||||
|                 return; | ||||
|             } | ||||
|             case "SKELETON", "WITHER_SKELETON", "GUARDIAN", "ELDER_GUARDIAN", "GHAST", "MAGMA_CUBE", "SQUID", "PIG_ZOMBIE", "HOGLIN", | ||||
|                     "ZOMBIFIED_PIGLIN", "PIGLIN", "PIGLIN_BRUTE", "ZOMBIE", "WITHER", "WITCH", "SPIDER", "CAVE_SPIDER", "SILVERFISH", | ||||
|                     "GIANT", "ENDERMAN", "CREEPER", "BLAZE", "SHULKER", "SNOWMAN" -> { | ||||
|             case "SKELETON": | ||||
|             case "WITHER_SKELETON": | ||||
|             case "GUARDIAN": | ||||
|             case "ELDER_GUARDIAN": | ||||
|             case "GHAST": | ||||
|             case "MAGMA_CUBE": | ||||
|             case "SQUID": | ||||
|             case "PIG_ZOMBIE": | ||||
|             case "HOGLIN": | ||||
|             case "ZOMBIFIED_PIGLIN": | ||||
|             case "PIGLIN": | ||||
|             case "PIGLIN_BRUTE": | ||||
|             case "ZOMBIE": | ||||
|             case "WITHER": | ||||
|             case "WITCH": | ||||
|             case "SPIDER": | ||||
|             case "CAVE_SPIDER": | ||||
|             case "SILVERFISH": | ||||
|             case "GIANT": | ||||
|             case "ENDERMAN": | ||||
|             case "CREEPER": | ||||
|             case "BLAZE": | ||||
|             case "SHULKER": | ||||
|             case "SNOWMAN": | ||||
|                 storeLiving((LivingEntity) entity); | ||||
|                 return; | ||||
|             } | ||||
|             case "IRON_GOLEM" -> { | ||||
|             case "IRON_GOLEM": | ||||
|                 if (((IronGolem) entity).isPlayerCreated()) { | ||||
|                     this.dataByte = (byte) 1; | ||||
|                 } else { | ||||
|                     this.dataByte = (byte) 0; | ||||
|                 } | ||||
|                 storeLiving((LivingEntity) entity); | ||||
|             } | ||||
|             // END LIVING // | ||||
|                 // END LIVING // | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -415,15 +465,20 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|         } | ||||
|         Entity entity; | ||||
|         switch (this.getType().toString()) { | ||||
|             case "DROPPED_ITEM" -> { | ||||
|             case "DROPPED_ITEM": | ||||
|                 return world.dropItem(location, this.stack); | ||||
|             } | ||||
|             case "PLAYER", "LEASH_HITCH" -> { | ||||
|             case "PLAYER": | ||||
|             case "LEASH_HITCH": | ||||
|                 return null; | ||||
|             } | ||||
|             case "ITEM_FRAME" -> entity = world.spawn(location, ItemFrame.class); | ||||
|             case "PAINTING" -> entity = world.spawn(location, Painting.class); | ||||
|             default -> entity = world.spawnEntity(location, this.getType()); | ||||
|             case "ITEM_FRAME": | ||||
|                 entity = world.spawn(location, ItemFrame.class); | ||||
|                 break; | ||||
|             case "PAINTING": | ||||
|                 entity = world.spawn(location, Painting.class); | ||||
|                 break; | ||||
|             default: | ||||
|                 entity = world.spawnEntity(location, this.getType()); | ||||
|                 break; | ||||
|         } | ||||
|         if (this.depth == 0) { | ||||
|             return entity; | ||||
| @@ -451,46 +506,72 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|             entity.setGravity(false); | ||||
|         } | ||||
|         switch (entity.getType().toString()) { | ||||
|             case "BOAT" -> { | ||||
|             case "BOAT": | ||||
|                 Boat boat = (Boat) entity; | ||||
|                 boat.setWoodType(TreeSpecies.values()[dataByte]); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "SLIME" -> { | ||||
|             case "SLIME": | ||||
|                 ((Slime) entity).setSize(this.dataByte); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "ARROW", "EGG", "ENDER_CRYSTAL", "ENDER_PEARL", "ENDER_SIGNAL", "DROPPED_ITEM", "EXPERIENCE_ORB", "FALLING_BLOCK", | ||||
|                     "FIREBALL", "FIREWORK", "FISHING_HOOK", "LEASH_HITCH", "LIGHTNING", "MINECART", "MINECART_COMMAND", | ||||
|                     "MINECART_MOB_SPAWNER", "MINECART_TNT", "PLAYER", "PRIMED_TNT", "SMALL_FIREBALL", "SNOWBALL", | ||||
|                     "SPLASH_POTION", "THROWN_EXP_BOTTLE", "SPECTRAL_ARROW", "SHULKER_BULLET", "AREA_EFFECT_CLOUD", | ||||
|                     "DRAGON_FIREBALL", "WITHER_SKULL", "MINECART_FURNACE", "LLAMA_SPIT", "TRIDENT", "UNKNOWN" -> { | ||||
|             case "ARROW": | ||||
|             case "EGG": | ||||
|             case "ENDER_CRYSTAL": | ||||
|             case "ENDER_PEARL": | ||||
|             case "ENDER_SIGNAL": | ||||
|             case "DROPPED_ITEM": | ||||
|             case "EXPERIENCE_ORB": | ||||
|             case "FALLING_BLOCK": | ||||
|             case "FIREBALL": | ||||
|             case "FIREWORK": | ||||
|             case "FISHING_HOOK": | ||||
|             case "LEASH_HITCH": | ||||
|             case "LIGHTNING": | ||||
|             case "MINECART": | ||||
|             case "MINECART_COMMAND": | ||||
|             case "MINECART_MOB_SPAWNER": | ||||
|             case "MINECART_TNT": | ||||
|             case "PLAYER": | ||||
|             case "PRIMED_TNT": | ||||
|             case "SMALL_FIREBALL": | ||||
|             case "SNOWBALL": | ||||
|             case "SPLASH_POTION": | ||||
|             case "THROWN_EXP_BOTTLE": | ||||
|             case "SPECTRAL_ARROW": | ||||
|             case "SHULKER_BULLET": | ||||
|             case "AREA_EFFECT_CLOUD": | ||||
|             case "DRAGON_FIREBALL": | ||||
|             case "WITHER_SKULL": | ||||
|             case "MINECART_FURNACE": | ||||
|             case "LLAMA_SPIT": | ||||
|             case "TRIDENT": | ||||
|             case "UNKNOWN": | ||||
|                 // Do this stuff later | ||||
|                 return entity; | ||||
|             } | ||||
|             // MISC // | ||||
|             case "ITEM_FRAME" -> { | ||||
|             case "ITEM_FRAME": | ||||
|                 ItemFrame itemframe = (ItemFrame) entity; | ||||
|                 itemframe.setRotation(Rotation.values()[this.dataByte]); | ||||
|                 itemframe.setItem(this.stack); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "PAINTING" -> { | ||||
|             case "PAINTING": | ||||
|                 Painting painting = (Painting) entity; | ||||
|                 painting.setFacingDirection(BlockFace.values()[this.dataByte], true); | ||||
|                 painting.setArt(Art.getByName(this.dataString), true); | ||||
|                 return entity; | ||||
|             } | ||||
|             // END MISC // | ||||
|             // INVENTORY HOLDER // | ||||
|             case "MINECART_CHEST", "MINECART_HOPPER" -> { | ||||
|             case "MINECART_CHEST": | ||||
|             case "MINECART_HOPPER": | ||||
|                 restoreInventory((InventoryHolder) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             // START LIVING ENTITY // | ||||
|             // START AGEABLE // | ||||
|             // START TAMEABLE // | ||||
|             case "HORSE", "LLAMA", "SKELETON_HORSE", "DONKEY", "MULE" -> { | ||||
|             case "HORSE": | ||||
|             case "LLAMA": | ||||
|             case "SKELETON_HORSE": | ||||
|             case "DONKEY": | ||||
|             case "MULE": | ||||
|                 AbstractHorse horse = (AbstractHorse) entity; | ||||
|                 horse.setJumpStrength(this.horse.jump); | ||||
|                 if (horse instanceof ChestedHorse) { | ||||
| @@ -505,16 +586,15 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 restoreLiving(horse); | ||||
|                 restoreInventory(horse); | ||||
|                 return entity; | ||||
|             } | ||||
|             // END INVENTORY HOLDER // | ||||
|             case "WOLF", "OCELOT" -> { | ||||
|             case "WOLF": | ||||
|             case "OCELOT": | ||||
|                 restoreTameable((Tameable) entity); | ||||
|                 restoreAgeable((Ageable) entity); | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             // END AGEABLE // | ||||
|             case "SHEEP" -> { | ||||
|             case "SHEEP": | ||||
|                 Sheep sheep = (Sheep) entity; | ||||
|                 if (this.dataByte == 1) { | ||||
|                     sheep.setSheared(true); | ||||
| @@ -525,22 +605,25 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 restoreAgeable(sheep); | ||||
|                 restoreLiving(sheep); | ||||
|                 return sheep; | ||||
|             } | ||||
|             case "VILLAGER", "CHICKEN", "COW", "TURTLE", "POLAR_BEAR", "MUSHROOM_COW", "PIG" -> { | ||||
|             case "VILLAGER": | ||||
|             case "CHICKEN": | ||||
|             case "COW": | ||||
|             case "TURTLE": | ||||
|             case "POLAR_BEAR": | ||||
|             case "MUSHROOM_COW": | ||||
|             case "PIG": | ||||
|                 restoreAgeable((Ageable) entity); | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             // END AGEABLE // | ||||
|             case "RABBIT" -> { | ||||
|             case "RABBIT": | ||||
|                 if (this.dataByte != 0) { | ||||
|                     ((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]); | ||||
|                 } | ||||
|                 restoreAgeable((Ageable) entity); | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "ARMOR_STAND" -> { | ||||
|             case "ARMOR_STAND": | ||||
|                 // CHECK positions | ||||
|                 ArmorStand stand = (ArmorStand) entity; | ||||
|                 if (this.inventory[0] != null) { | ||||
| @@ -610,38 +693,56 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { | ||||
|                 } | ||||
|                 restoreLiving(stand); | ||||
|                 return stand; | ||||
|             } | ||||
|             case "BAT" -> { | ||||
|             case "BAT": | ||||
|                 if (this.dataByte != 0) { | ||||
|                     ((Bat) entity).setAwake(true); | ||||
|                 } | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "ENDER_DRAGON" -> { | ||||
|             case "ENDER_DRAGON": | ||||
|                 if (this.dataByte != 0) { | ||||
|                     ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); | ||||
|                 } | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "ENDERMITE", "GHAST", "MAGMA_CUBE", "SQUID", "PIG_ZOMBIE", "HOGLIN", "PIGLIN", "ZOMBIFIED_PIGLIN", "PIGLIN_BRUTE", "ZOMBIE", "WITHER", "WITCH", "SPIDER", "CAVE_SPIDER", "SILVERFISH", "GIANT", "ENDERMAN", "CREEPER", "BLAZE", "SNOWMAN", "SHULKER", "GUARDIAN", "ELDER_GUARDIAN", "SKELETON", "WITHER_SKELETON" -> { | ||||
|             case "ENDERMITE": | ||||
|             case "GHAST": | ||||
|             case "MAGMA_CUBE": | ||||
|             case "SQUID": | ||||
|             case "PIG_ZOMBIE": | ||||
|             case "HOGLIN": | ||||
|             case "PIGLIN": | ||||
|             case "ZOMBIFIED_PIGLIN": | ||||
|             case "PIGLIN_BRUTE": | ||||
|             case "ZOMBIE": | ||||
|             case "WITHER": | ||||
|             case "WITCH": | ||||
|             case "SPIDER": | ||||
|             case "CAVE_SPIDER": | ||||
|             case "SILVERFISH": | ||||
|             case "GIANT": | ||||
|             case "ENDERMAN": | ||||
|             case "CREEPER": | ||||
|             case "BLAZE": | ||||
|             case "SNOWMAN": | ||||
|             case "SHULKER": | ||||
|             case "GUARDIAN": | ||||
|             case "ELDER_GUARDIAN": | ||||
|             case "SKELETON": | ||||
|             case "WITHER_SKELETON": | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             case "IRON_GOLEM" -> { | ||||
|             case "IRON_GOLEM": | ||||
|                 if (this.dataByte != 0) { | ||||
|                     ((IronGolem) entity).setPlayerCreated(true); | ||||
|                 } | ||||
|                 restoreLiving((LivingEntity) entity); | ||||
|                 return entity; | ||||
|             } | ||||
|             default -> { | ||||
|             default: | ||||
|                 if (Settings.DEBUG) { | ||||
|                     LOGGER.info("Could not identify entity: {}", entity.getType()); | ||||
|                 } | ||||
|                 return entity; | ||||
|             } | ||||
|             // END LIVING | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -34,12 +34,9 @@ import com.plotsquared.core.queue.ZeroedDelegateScopedQueueCoordinator; | ||||
| import com.plotsquared.core.util.ChunkManager; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| import com.sk89q.worldedit.math.BlockVector2; | ||||
| import com.sk89q.worldedit.math.BlockVector3; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.bukkit.HeightMap; | ||||
| import org.bukkit.NamespacedKey; | ||||
| import org.bukkit.Registry; | ||||
| import org.bukkit.World; | ||||
| import org.bukkit.block.Biome; | ||||
| import org.bukkit.generator.BiomeProvider; | ||||
| @@ -51,17 +48,13 @@ import org.jetbrains.annotations.NotNull; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.EnumSet; | ||||
| import java.util.List; | ||||
| import java.util.Random; | ||||
| import java.util.Set; | ||||
|  | ||||
| import static java.util.function.Predicate.not; | ||||
|  | ||||
| public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitPlotGenerator.class.getSimpleName()); | ||||
|     private static final Logger LOGGER =  LogManager.getLogger("PlotSquared/" + BukkitPlotGenerator.class.getSimpleName()); | ||||
|  | ||||
|     @SuppressWarnings("unused") | ||||
|     public final boolean PAPER_ASYNC_SAFE = true; | ||||
| @@ -192,6 +185,12 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap | ||||
|         world.setWaterAnimalSpawnLimit(limit); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The entire method is deprecated, but kept for compatibility with versions lower than or equal to 1.16.2. | ||||
|      * The method will be removed in future versions, because WorldEdit and FastAsyncWorldEdit only support the latest point | ||||
|      * release. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "6.11.0") | ||||
|     @Override | ||||
|     public void generateNoise( | ||||
|             @NotNull final WorldInfo worldInfo, | ||||
| @@ -284,14 +283,9 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap | ||||
|         return super.getBaseHeight(worldInfo, random, x, z, heightMap); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The entire method is deprecated, but kept for compatibility with versions lower than or equal to 1.16.2. | ||||
|      * The method will be removed in future versions, because WorldEdit and FastAsyncWorldEdit only support the latest point | ||||
|      * release. | ||||
|      */ | ||||
|     @SuppressWarnings("deprecation") // The entire method is deprecated, but kept for compatibility with <=1.16.2 | ||||
|     @Override | ||||
|     @Deprecated(since = "7.0.0") | ||||
|     @Deprecated(since = "TODO") | ||||
|     public @NonNull ChunkData generateChunkData( | ||||
|             @NonNull World world, @NonNull Random random, int x, int z, @NonNull BiomeGrid biome | ||||
|     ) { | ||||
| @@ -299,8 +293,8 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap | ||||
|             if (this.platformGenerator != this) { | ||||
|                 return this.platformGenerator.generateChunkData(world, random, x, z, biome); | ||||
|             } else { | ||||
|                 // Throw exception to be caught by the server that indicates the new generation API is being used. | ||||
|                 throw new UnsupportedOperationException("Using new generation methods. This method is unsupported."); | ||||
|                 // Return super as it will throw an exception caught by the server that will mean this method is no longer used. | ||||
|                 return super.generateChunkData(world, random, x, z, biome); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -421,14 +415,9 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap | ||||
|         if (lastPlotArea != null && name.equals(this.levelName) && chunkX == lastChunkX && chunkZ == lastChunkZ) { | ||||
|             return lastPlotArea; | ||||
|         } | ||||
|         BlockVector3 loc = BlockVector3.at(chunkX << 4, 0, chunkZ << 4); | ||||
|         if (lastPlotArea != null && lastPlotArea.getRegion().contains(loc) && lastPlotArea.getRegion().contains(loc)) { | ||||
|             return lastPlotArea; | ||||
|         } | ||||
|         PlotArea area = UncheckedWorldLocation.at(name, loc).getPlotArea(); | ||||
|         PlotArea area = UncheckedWorldLocation.at(name, chunkX << 4, 0, chunkZ << 4).getPlotArea(); | ||||
|         if (area == null) { | ||||
|             throw new IllegalStateException(String.format( | ||||
|                     "Cannot generate chunk that does not belong to a plot area. World: %s", | ||||
|             throw new IllegalStateException(String.format("Cannot generate chunk that does not belong to a plot area. World: %s", | ||||
|                     name | ||||
|             )); | ||||
|         } | ||||
| @@ -445,16 +434,9 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap | ||||
|         private static final List<Biome> BIOMES; | ||||
|  | ||||
|         static { | ||||
|             Set<Biome> disabledBiomes = EnumSet.of(Biome.CUSTOM); | ||||
|             if (PlotSquared.platform().serverVersion()[1] <= 19) { | ||||
|                 final Biome cherryGrove = Registry.BIOME.get(NamespacedKey.minecraft("cherry_grove")); | ||||
|                 if (cherryGrove != null) { | ||||
|                     disabledBiomes.add(cherryGrove); | ||||
|                 } | ||||
|             } | ||||
|             BIOMES = Arrays.stream(Biome.values()) | ||||
|                     .filter(not(disabledBiomes::contains)) | ||||
|                     .toList(); | ||||
|             ArrayList<Biome> biomes = new ArrayList<>(List.of(Biome.values())); | ||||
|             biomes.remove(Biome.CUSTOM); | ||||
|             BIOMES = List.copyOf(biomes); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|   | ||||
| @@ -18,12 +18,16 @@ | ||||
|  */ | ||||
| package com.plotsquared.bukkit.inject; | ||||
|  | ||||
| import cloud.commandframework.CommandManager; | ||||
| import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; | ||||
| import cloud.commandframework.paper.PaperCommandManager; | ||||
| import com.google.inject.AbstractModule; | ||||
| import com.google.inject.Provides; | ||||
| import com.google.inject.Singleton; | ||||
| import com.google.inject.assistedinject.FactoryModuleBuilder; | ||||
| import com.plotsquared.bukkit.BukkitPlatform; | ||||
| import com.plotsquared.bukkit.listener.SingleWorldListener; | ||||
| import com.plotsquared.bukkit.player.BukkitPlayer; | ||||
| import com.plotsquared.bukkit.player.BukkitPlayerManager; | ||||
| import com.plotsquared.bukkit.queue.BukkitChunkCoordinator; | ||||
| import com.plotsquared.bukkit.queue.BukkitQueueCoordinator; | ||||
| @@ -47,6 +51,8 @@ import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; | ||||
| import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; | ||||
| import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; | ||||
| import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; | ||||
| import com.plotsquared.core.player.ConsolePlayer; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.world.DefaultPlotAreaManager; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.plot.world.SinglePlotAreaManager; | ||||
| @@ -68,10 +74,14 @@ import com.sk89q.worldedit.extension.platform.Actor; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.command.ConsoleCommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.plugin.java.JavaPlugin; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.function.Function; | ||||
|  | ||||
| public class BukkitModule extends AbstractModule { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitModule.class.getSimpleName()); | ||||
| @@ -145,4 +155,27 @@ public class BukkitModule extends AbstractModule { | ||||
|         return EconHandler.nullEconHandler(); | ||||
|     } | ||||
|  | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     @NonNull CommandManager<PlotPlayer<?>> provideCommandManager() throws Exception { | ||||
|         final Function<PlotPlayer<?>, CommandSender> plotToPlatform = plotPlayer -> { | ||||
|             if (plotPlayer instanceof BukkitPlayer bukkitPlayer) { | ||||
|                 return bukkitPlayer.getPlatformPlayer(); | ||||
|             } | ||||
|             return Bukkit.getConsoleSender(); | ||||
|         }; | ||||
|         final Function<CommandSender, PlotPlayer<?>> platformToPlot = commandSender -> { | ||||
|             if (commandSender instanceof Player player) { | ||||
|                 return BukkitUtil.adapt(player); | ||||
|             } | ||||
|             return ConsolePlayer.getConsole(); | ||||
|         }; | ||||
|  | ||||
|         return new PaperCommandManager<>( | ||||
|                 this.bukkitPlatform, | ||||
|                 AsynchronousCommandExecutionCoordinator.<PlotPlayer<?>>builder().withSynchronousParsing().build(), | ||||
|                 platformToPlot, | ||||
|                 plotToPlatform | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -72,7 +72,6 @@ import org.bukkit.block.BlockFace; | ||||
| import org.bukkit.block.BlockState; | ||||
| import org.bukkit.block.data.BlockData; | ||||
| import org.bukkit.block.data.type.Dispenser; | ||||
| import org.bukkit.block.data.type.Farmland; | ||||
| import org.bukkit.entity.Entity; | ||||
| import org.bukkit.entity.Fireball; | ||||
| import org.bukkit.entity.Player; | ||||
| @@ -747,35 +746,20 @@ public class BlockEventListener implements Listener { | ||||
|         Block block = event.getBlock(); | ||||
|         Location location = BukkitUtil.adapt(block.getLocation()); | ||||
|         PlotArea area = location.getPlotArea(); | ||||
|  | ||||
|         if (area == null) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         Plot plot = area.getOwnedPlot(location); | ||||
|  | ||||
|         if (plot == null) { | ||||
|             event.setCancelled(true); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (block.getBlockData() instanceof Farmland farmland && event | ||||
|                 .getNewState() | ||||
|                 .getBlockData() instanceof Farmland newFarmland) { | ||||
|             int currentMoisture = farmland.getMoisture(); | ||||
|             int newMoisture = newFarmland.getMoisture(); | ||||
|  | ||||
|             // farmland gets moisturizes | ||||
|             if (newMoisture > currentMoisture) { | ||||
|                 return; | ||||
|         Material blockType = block.getType(); | ||||
|         if (blockType == Material.FARMLAND) { | ||||
|             if (!plot.getFlag(SoilDryFlag.class)) { | ||||
|                 plot.debug("Soil could not dry because soil-dry = false"); | ||||
|                 event.setCancelled(true); | ||||
|             } | ||||
|  | ||||
|             if (plot.getFlag(SoilDryFlag.class)) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             plot.debug("Soil could not dry because soil-dry = false"); | ||||
|             event.setCancelled(true); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1116,7 +1100,6 @@ public class BlockEventListener implements Listener { | ||||
|             if (plot != null) { | ||||
|                 plot.debug("Explosion was cancelled because explosion = false"); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         event.blockList().removeIf(blox -> !plot.equals(area.getOwnedPlot(BukkitUtil.adapt(blox.getLocation())))); | ||||
|     } | ||||
|   | ||||
| @@ -26,7 +26,6 @@ import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.flag.implementations.CopperOxideFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| import org.bukkit.Material; | ||||
| import org.bukkit.block.Block; | ||||
| @@ -93,16 +92,12 @@ public class BlockEventListener117 implements Listener { | ||||
|         } | ||||
|  | ||||
|         Plot plot = location.getOwnedPlot(); | ||||
|         if (plot == null && !PlotFlagUtil.isAreaRoadFlagsAndFlagEquals( | ||||
|                 area, | ||||
|                 MiscInteractFlag.class, | ||||
|                 true | ||||
|         ) || plot != null && (!plot.getFlag(MiscInteractFlag.class) || !plot.getFlag(SculkSensorInteractFlag.class))) { | ||||
|         if (plot == null && !PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, MiscInteractFlag.class, true) || plot != null && !plot.getFlag( | ||||
|                 MiscInteractFlag.class)) { | ||||
|             if (plotPlayer != null) { | ||||
|                 if (plot != null) { | ||||
|                     if (!plot.isAdded(plotPlayer.getUUID())) { | ||||
|                         plot.debug(plotPlayer.getName() + " couldn't trigger sculk sensors because both " + | ||||
|                                 "sculk-sensor-interact and misc-interact = false"); | ||||
|                         plot.debug(plotPlayer.getName() + " couldn't trigger sculk sensors because misc-interact = false"); | ||||
|                         event.setCancelled(true); | ||||
|                     } | ||||
|                 } | ||||
| @@ -113,15 +108,13 @@ public class BlockEventListener117 implements Listener { | ||||
|                 if (plot != null) { | ||||
|                     if (itemThrower == null && (itemThrower = item.getOwner()) == null) { | ||||
|                         plot.debug( | ||||
|                                 "A thrown item couldn't trigger sculk sensors because both sculk-sensor-interact and " + | ||||
|                                         "misc-interact = false and the item's owner could not be resolved."); | ||||
|                                 "A thrown item couldn't trigger sculk sensors because misc-interact = false and the item's owner could not be resolved."); | ||||
|                         event.setCancelled(true); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (!plot.isAdded(itemThrower)) { | ||||
|                         if (!plot.isAdded(itemThrower)) { | ||||
|                             plot.debug("A thrown item couldn't trigger sculk sensors because both sculk-sensor-interact and " + | ||||
|                                     "misc-interact = false"); | ||||
|                             plot.debug("A thrown item couldn't trigger sculk sensors because misc-interact = false"); | ||||
|                             event.setCancelled(true); | ||||
|                         } | ||||
|                     } | ||||
| @@ -140,6 +133,7 @@ public class BlockEventListener117 implements Listener { | ||||
|         if (area == null) { | ||||
|             for (int i = blocks.size() - 1; i >= 0; i--) { | ||||
|                 Location blockLocation = BukkitUtil.adapt(blocks.get(i).getLocation()); | ||||
|                 blockLocation = BukkitUtil.adapt(blocks.get(i).getLocation()); | ||||
|                 if (blockLocation.isPlotArea()) { | ||||
|                     blocks.remove(i); | ||||
|                 } | ||||
|   | ||||
| @@ -234,8 +234,7 @@ public class ChunkListener implements Listener { | ||||
|         Chunk chunk = event.getChunk(); | ||||
|         if (Settings.Chunk_Processor.AUTO_TRIM) { | ||||
|             String world = chunk.getWorld().getName(); | ||||
|             if ((!Settings.Enabled_Components.WORLDS || !SinglePlotArea.isSinglePlotWorld(world)) && this.plotAreaManager.hasPlotArea( | ||||
|                     world)) { | ||||
|             if ((!Settings.Enabled_Components.WORLDS || !SinglePlotArea.isSinglePlotWorld(world)) && this.plotAreaManager.hasPlotArea(world)) { | ||||
|                 if (unloadChunk(world, chunk, true)) { | ||||
|                     return; | ||||
|                 } | ||||
|   | ||||
| @@ -145,38 +145,54 @@ public class EntityEventListener implements Listener { | ||||
|         } | ||||
|         CreatureSpawnEvent.SpawnReason reason = event.getSpawnReason(); | ||||
|         switch (reason.toString()) { | ||||
|             case "DISPENSE_EGG", "EGG", "OCELOT_BABY", "SPAWNER_EGG" -> { | ||||
|             case "DISPENSE_EGG": | ||||
|             case "EGG": | ||||
|             case "OCELOT_BABY": | ||||
|             case "SPAWNER_EGG": | ||||
|                 if (!area.isSpawnEggs()) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "REINFORCEMENTS", "NATURAL", "MOUNT", "PATROL", "RAID", "SHEARED", "SILVERFISH_BLOCK", "ENDER_PEARL", | ||||
|                     "TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN", "NETHER_PORTAL", "DEFAULT", | ||||
|                     "DUPLICATION", "FROZEN", "SPELL" -> { | ||||
|                 break; | ||||
|             case "REINFORCEMENTS": | ||||
|             case "NATURAL": | ||||
|             case "MOUNT": | ||||
|             case "PATROL": | ||||
|             case "RAID": | ||||
|             case "SHEARED": | ||||
|             case "SILVERFISH_BLOCK": | ||||
|             case "ENDER_PEARL": | ||||
|             case "TRAP": | ||||
|             case "VILLAGE_DEFENSE": | ||||
|             case "VILLAGE_INVASION": | ||||
|             case "BEEHIVE": | ||||
|             case "CHUNK_GEN": | ||||
|                 if (!area.isMobSpawning()) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "BREEDING" -> { | ||||
|                 break; | ||||
|             case "BREEDING": | ||||
|                 if (!area.isSpawnBreeding()) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "BUILD_IRONGOLEM", "BUILD_SNOWMAN", "BUILD_WITHER", "CUSTOM" -> { | ||||
|                 break; | ||||
|             case "BUILD_IRONGOLEM": | ||||
|             case "BUILD_SNOWMAN": | ||||
|             case "BUILD_WITHER": | ||||
|             case "CUSTOM": | ||||
|                 if (!area.isSpawnCustom() && entity.getType() != EntityType.ARMOR_STAND) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "SPAWNER" -> { | ||||
|                 break; | ||||
|             case "SPAWNER": | ||||
|                 if (!area.isMobSpawnerSpawning()) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|                 break; | ||||
|         } | ||||
|         Plot plot = area.getOwnedPlotAbs(location); | ||||
|         if (plot == null) { | ||||
|   | ||||
| @@ -43,10 +43,10 @@ import com.plotsquared.core.plot.flag.implementations.DoneFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag; | ||||
| import com.plotsquared.core.plot.flag.types.BooleanFlag; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| import org.bukkit.Chunk; | ||||
| import org.bukkit.block.Block; | ||||
| import org.bukkit.block.TileState; | ||||
| @@ -178,41 +178,59 @@ public class PaperListener implements Listener { | ||||
|         } | ||||
|         CreatureSpawnEvent.SpawnReason reason = event.getReason(); | ||||
|         switch (reason.toString()) { | ||||
|             case "DISPENSE_EGG", "EGG", "OCELOT_BABY", "SPAWNER_EGG" -> { | ||||
|             case "DISPENSE_EGG": | ||||
|             case "EGG": | ||||
|             case "OCELOT_BABY": | ||||
|             case "SPAWNER_EGG": | ||||
|                 if (!area.isSpawnEggs()) { | ||||
|                     event.setShouldAbortSpawn(true); | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "REINFORCEMENTS", "NATURAL", "MOUNT", "PATROL", "RAID", "SHEARED", "SILVERFISH_BLOCK", "ENDER_PEARL", "TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN" -> { | ||||
|                 break; | ||||
|             case "REINFORCEMENTS": | ||||
|             case "NATURAL": | ||||
|             case "MOUNT": | ||||
|             case "PATROL": | ||||
|             case "RAID": | ||||
|             case "SHEARED": | ||||
|             case "SILVERFISH_BLOCK": | ||||
|             case "ENDER_PEARL": | ||||
|             case "TRAP": | ||||
|             case "VILLAGE_DEFENSE": | ||||
|             case "VILLAGE_INVASION": | ||||
|             case "BEEHIVE": | ||||
|             case "CHUNK_GEN": | ||||
|                 if (!area.isMobSpawning()) { | ||||
|                     event.setShouldAbortSpawn(true); | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "BREEDING" -> { | ||||
|                 break; | ||||
|             case "BREEDING": | ||||
|                 if (!area.isSpawnBreeding()) { | ||||
|                     event.setShouldAbortSpawn(true); | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "BUILD_IRONGOLEM", "BUILD_SNOWMAN", "BUILD_WITHER", "CUSTOM" -> { | ||||
|                 break; | ||||
|             case "BUILD_IRONGOLEM": | ||||
|             case "BUILD_SNOWMAN": | ||||
|             case "BUILD_WITHER": | ||||
|             case "CUSTOM": | ||||
|                 if (!area.isSpawnCustom() && event.getType() != EntityType.ARMOR_STAND) { | ||||
|                     event.setShouldAbortSpawn(true); | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             case "SPAWNER" -> { | ||||
|                 break; | ||||
|             case "SPAWNER": | ||||
|                 if (!area.isMobSpawnerSpawning()) { | ||||
|                     event.setShouldAbortSpawn(true); | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|                 break; | ||||
|         } | ||||
|         Plot plot = location.getOwnedPlotAbs(); | ||||
|         if (plot == null) { | ||||
| @@ -439,11 +457,9 @@ public class PaperListener implements Listener { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private boolean getBooleanFlagValue( | ||||
|             @NonNull FlagContainer container, | ||||
|             @NonNull Class<? extends BooleanFlag<?>> flagClass, | ||||
|             boolean defaultValue | ||||
|     ) { | ||||
|     private boolean getBooleanFlagValue(@NonNull FlagContainer container, | ||||
|                                         @NonNull Class<? extends BooleanFlag<?>> flagClass, | ||||
|                                         boolean defaultValue) { | ||||
|         BooleanFlag<?> flag = container.getFlag(flagClass); | ||||
|         return flag == null ? defaultValue : flag.getValue(); | ||||
|     } | ||||
|   | ||||
| @@ -273,7 +273,8 @@ public class PlayerEventListener implements Listener { | ||||
|         Plot plot = plotPlayer.getCurrentPlot(); | ||||
|         // Check WorldEdit | ||||
|         switch (parts[0]) { | ||||
|             case "up", "worldedit:up" -> { | ||||
|             case "up": | ||||
|             case "worldedit:up": | ||||
|                 if (plot == null || (!plot.isAdded(plotPlayer.getUUID()) && !plotPlayer.hasPermission( | ||||
|                         Permission.PERMISSION_ADMIN_BUILD_OTHER, | ||||
|                         true | ||||
| @@ -281,7 +282,6 @@ public class PlayerEventListener implements Listener { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (plot == null && !area.isRoadFlags()) { | ||||
|             return; | ||||
| @@ -572,8 +572,7 @@ public class PlayerEventListener implements Listener { | ||||
|             if (now == null) { | ||||
|                 try (final MetaDataAccess<Boolean> kickAccess = | ||||
|                              pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { | ||||
|                     if (lastPlot != null && !plotListener.plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse( | ||||
|                             false)) { | ||||
|                     if (lastPlot != null && !plotListener.plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse(false)) { | ||||
|                         pp.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.no_permission_event"), | ||||
|                                 TagResolver.resolver( | ||||
| @@ -666,8 +665,7 @@ public class PlayerEventListener implements Listener { | ||||
|             if (plot == null) { | ||||
|                 try (final MetaDataAccess<Boolean> kickAccess = | ||||
|                              pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { | ||||
|                     if (lastPlot != null && !plotListener.plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse( | ||||
|                             false)) { | ||||
|                     if (lastPlot != null && !plotListener.plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse(false)) { | ||||
|                         pp.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.no_permission_event"), | ||||
|                                 TagResolver.resolver( | ||||
| @@ -1116,13 +1114,13 @@ public class PlayerEventListener implements Listener { | ||||
|         Location location = BukkitUtil.adapt(block.getLocation()); | ||||
|         Action action = event.getAction(); | ||||
|         switch (action) { | ||||
|             case PHYSICAL -> { | ||||
|             case PHYSICAL: { | ||||
|                 eventType = PlayerBlockEventType.TRIGGER_PHYSICAL; | ||||
|                 blocktype1 = BukkitAdapter.asBlockType(block.getType()); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             //todo rearrange the right click code. it is all over the place. | ||||
|             case RIGHT_CLICK_BLOCK -> { | ||||
|             case RIGHT_CLICK_BLOCK: { | ||||
|                 Material blockType = block.getType(); | ||||
|                 eventType = PlayerBlockEventType.INTERACT_BLOCK; | ||||
|                 blocktype1 = BukkitAdapter.asBlockType(block.getType()); | ||||
| @@ -1144,16 +1142,21 @@ public class PlayerEventListener implements Listener { | ||||
|  | ||||
|                 // in the following, lb needs to have the material of the item in hand i.e. type | ||||
|                 switch (type.toString()) { | ||||
|                     case "REDSTONE", "STRING", "PUMPKIN_SEEDS", "MELON_SEEDS", "COCOA_BEANS", "WHEAT_SEEDS", "BEETROOT_SEEDS", | ||||
|                             "SWEET_BERRIES", "GLOW_BERRIES" -> { | ||||
|                     case "REDSTONE": | ||||
|                     case "STRING": | ||||
|                     case "PUMPKIN_SEEDS": | ||||
|                     case "MELON_SEEDS": | ||||
|                     case "COCOA_BEANS": | ||||
|                     case "WHEAT_SEEDS": | ||||
|                     case "BEETROOT_SEEDS": | ||||
|                     case "SWEET_BERRIES": | ||||
|                     case "GLOW_BERRIES": | ||||
|                         return; | ||||
|                     } | ||||
|                     default -> { | ||||
|                     default: | ||||
|                         //eventType = PlayerBlockEventType.PLACE_BLOCK; | ||||
|                         if (type.isBlock()) { | ||||
|                             return; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 if (PaperLib.isPaper()) { | ||||
|                     if (MaterialTags.SPAWN_EGGS.isTagged(type) || Material.EGG.equals(type)) { | ||||
| @@ -1186,8 +1189,9 @@ public class PlayerEventListener implements Listener { | ||||
|                     eventType = PlayerBlockEventType.READ; | ||||
|                     break; | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             case LEFT_CLICK_BLOCK -> { | ||||
|             case LEFT_CLICK_BLOCK: { | ||||
|                 Material blockType = block.getType(); | ||||
|  | ||||
|                 // todo: when the code above is rearranged, it would be great to beautify this as well. | ||||
| @@ -1198,10 +1202,10 @@ public class PlayerEventListener implements Listener { | ||||
|  | ||||
|                 eventType = PlayerBlockEventType.INTERACT_BLOCK; | ||||
|                 blocktype1 = BukkitAdapter.asBlockType(block.getType()); | ||||
|                 break; | ||||
|             } | ||||
|             default -> { | ||||
|             default: | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         if (this.worldEdit != null && pp.getAttribute("worldedit")) { | ||||
|             if (event.getMaterial() == Material.getMaterial(this.worldEdit.getConfiguration().wandItem)) { | ||||
|   | ||||
| @@ -30,9 +30,9 @@ import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.PlotHandler; | ||||
| import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| import org.bukkit.entity.Entity; | ||||
| import org.bukkit.entity.LivingEntity; | ||||
| import org.bukkit.entity.Player; | ||||
|   | ||||
| @@ -0,0 +1,63 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.bukkit.managers; | ||||
|  | ||||
| /* | ||||
| import com.google.inject.Singleton; | ||||
| import org.bukkit.World; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import se.hyperver.hyperverse.Hyperverse; | ||||
| import se.hyperver.hyperverse.world.WorldConfiguration; | ||||
| import se.hyperver.hyperverse.world.WorldConfigurationBuilder; | ||||
| import se.hyperver.hyperverse.world.WorldFeatures; | ||||
| import se.hyperver.hyperverse.world.WorldType; | ||||
|  | ||||
| Hyperverse implementation is currently put on ice until Hyperverse is released on a stable line and deployed to the central | ||||
| repository. | ||||
|  | ||||
| @Singleton | ||||
| public class HyperverseWorldManager extends BukkitWorldManager { | ||||
|  | ||||
|     @Override | ||||
|     public @Nullable World handleWorldCreation(@NonNull String worldName, @Nullable String generator) { | ||||
|         // First let Bukkit register the world | ||||
|         this.setGenerator(worldName, generator); | ||||
|         // Create the world | ||||
|         final WorldConfigurationBuilder worldConfigurationBuilder = WorldConfiguration.builder() | ||||
|                 .setName(worldName).setType(WorldType.OVER_WORLD); | ||||
|         if (generator != null) { | ||||
|             worldConfigurationBuilder.setGenerator(generator).setWorldFeatures(WorldFeatures.FLATLAND); | ||||
|         } | ||||
|         try { | ||||
|             return Hyperverse.getApi().createWorld(worldConfigurationBuilder.createWorldConfiguration()) | ||||
|                     .getBukkitWorld(); | ||||
|         } catch (final Exception e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return "bukkit-hyperverse"; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  */ | ||||
| @@ -52,7 +52,7 @@ public class MVdWPlaceholders { | ||||
|  | ||||
|     @Subscribe | ||||
|     public void onNewPlaceholder(final PlaceholderRegistry.@NonNull PlaceholderAddedEvent event) { | ||||
|         this.addPlaceholder(event.placeholder()); | ||||
|         this.addPlaceholder(event.getPlaceholder()); | ||||
|     } | ||||
|  | ||||
|     private void addPlaceholder(final @NonNull Placeholder placeholder) { | ||||
|   | ||||
| @@ -43,7 +43,7 @@ public class BukkitOfflinePlayer implements OfflinePlotPlayer { | ||||
|      */ | ||||
|     public BukkitOfflinePlayer( | ||||
|             final @NonNull OfflinePlayer player, final @NonNull | ||||
|     PermissionHandler permissionHandler | ||||
|             PermissionHandler permissionHandler | ||||
|     ) { | ||||
|         this.player = player; | ||||
|         this.permissionProfile = permissionHandler.getPermissionProfile(this) | ||||
|   | ||||
| @@ -176,10 +176,6 @@ public class BukkitPlayer extends PlotPlayer<Player> { | ||||
|             final Set<PermissionAttachmentInfo> effective = player.getEffectivePermissions(); | ||||
|             if (!effective.isEmpty()) { | ||||
|                 for (PermissionAttachmentInfo attach : effective) { | ||||
|                     // Ignore all "false" permissions | ||||
|                     if (!attach.getValue()) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     String permStr = attach.getPermission(); | ||||
|                     if (permStr.startsWith(stubPlus)) { | ||||
|                         hasAny = true; | ||||
|   | ||||
| @@ -270,7 +270,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { | ||||
|             if (getChunkObject() instanceof Chunk chunkObject) { | ||||
|                 existing = chunkObject.getBlock(x & 15, y, z & 15); | ||||
|             } else { | ||||
|                 existing = getBukkitWorld().getBlockAt(x, y, z); | ||||
|                  existing = getBukkitWorld().getBlockAt(x, y, z); | ||||
|             } | ||||
|             final BlockState existingBaseBlock = BukkitAdapter.adapt(existing.getBlockData()); | ||||
|             if (BukkitBlockUtil.get(existing).equals(existingBaseBlock) && existing.getBlockData().matches(blockData)) { | ||||
|   | ||||
| @@ -62,6 +62,7 @@ public class GenChunk extends ZeroedDelegateScopedQueueCoordinator { | ||||
|     /** | ||||
|      * @param minY minimum world Y, inclusive | ||||
|      * @param maxY maximum world Y, inclusive | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public GenChunk(int minY, int maxY) { | ||||
| @@ -109,9 +110,9 @@ public class GenChunk extends ZeroedDelegateScopedQueueCoordinator { | ||||
|      */ | ||||
|     public void setChunk(@NonNull ChunkWrapper wrap) { | ||||
|         chunk = null; | ||||
|         world = wrap.world(); | ||||
|         chunkX = wrap.x(); | ||||
|         chunkZ = wrap.z(); | ||||
|         world = wrap.world; | ||||
|         chunkX = wrap.x; | ||||
|         chunkZ = wrap.z; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -18,8 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.bukkit.schematic; | ||||
|  | ||||
| import com.destroystokyo.paper.profile.PlayerProfile; | ||||
| import com.destroystokyo.paper.profile.ProfileProperty; | ||||
| import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.sk89q.jnbt.ByteTag; | ||||
| import com.sk89q.jnbt.CompoundTag; | ||||
| @@ -30,20 +28,13 @@ import com.sk89q.jnbt.Tag; | ||||
| import com.sk89q.worldedit.blocks.BaseItemStack; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| import com.sk89q.worldedit.world.item.ItemType; | ||||
| import io.papermc.lib.PaperLib; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.ChatColor; | ||||
| import org.bukkit.DyeColor; | ||||
| import org.bukkit.World; | ||||
| import org.bukkit.block.Banner; | ||||
| import org.bukkit.block.Block; | ||||
| import org.bukkit.block.Container; | ||||
| import org.bukkit.block.Sign; | ||||
| import org.bukkit.block.Skull; | ||||
| import org.bukkit.block.banner.Pattern; | ||||
| import org.bukkit.block.banner.PatternType; | ||||
| import org.bukkit.enchantments.Enchantment; | ||||
| import org.bukkit.inventory.Inventory; | ||||
| import org.bukkit.inventory.ItemStack; | ||||
| @@ -54,15 +45,11 @@ import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.Objects; | ||||
| import java.util.UUID; | ||||
|  | ||||
| public class StateWrapper { | ||||
|  | ||||
|     public CompoundTag tag; | ||||
|  | ||||
|     private boolean paperErrorTextureSent = false; | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + StateWrapper.class.getSimpleName()); | ||||
|     public org.bukkit.block.BlockState state = null; | ||||
|     public CompoundTag tag = null; | ||||
|  | ||||
|     public StateWrapper(CompoundTag tag) { | ||||
|         this.tag = tag; | ||||
| @@ -240,64 +227,15 @@ public class StateWrapper { | ||||
|                         return true; | ||||
|                     } | ||||
|                     String player = skullOwner.getString("Name"); | ||||
|  | ||||
|                     if (player != null && !player.isEmpty()) { | ||||
|                         try { | ||||
|                             skull.setOwningPlayer(Bukkit.getOfflinePlayer(player)); | ||||
|                             skull.update(true); | ||||
|                         } catch (Exception e) { | ||||
|                             e.printStackTrace(); | ||||
|                         } | ||||
|                         return true; | ||||
|                     } | ||||
|  | ||||
|                     final CompoundTag properties = (CompoundTag) skullOwner.getValue().get("Properties"); | ||||
|                     if (properties == null) { | ||||
|                     if (player == null || player.isEmpty()) { | ||||
|                         return false; | ||||
|                     } | ||||
|                     final ListTag textures = properties.getListTag("textures"); | ||||
|                     if (textures.getValue().isEmpty()) { | ||||
|                         return false; | ||||
|                     try { | ||||
|                         skull.setOwningPlayer(Bukkit.getOfflinePlayer(player)); | ||||
|                         skull.update(true); | ||||
|                     } catch (Exception e) { | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
|                     final CompoundTag textureCompound = (CompoundTag) textures.getValue().get(0); | ||||
|                     if (textureCompound == null) { | ||||
|                         return false; | ||||
|                     } | ||||
|                     String textureValue = textureCompound.getString("Value"); | ||||
|                     if (textureValue == null) { | ||||
|                         return false; | ||||
|                     } | ||||
|                     if (!PaperLib.isPaper()) { | ||||
|                         if (!paperErrorTextureSent) { | ||||
|                             paperErrorTextureSent = true; | ||||
|                             LOGGER.error("Failed to populate skull data in your road schematic - This is a Spigot limitation."); | ||||
|                         } | ||||
|                         return false; | ||||
|                     } | ||||
|                     final PlayerProfile profile = Bukkit.createProfile(UUID.randomUUID()); | ||||
|                     profile.setProperty(new ProfileProperty("textures", textureValue)); | ||||
|                     skull.setPlayerProfile(profile); | ||||
|                     skull.update(true); | ||||
|                     return true; | ||||
|  | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|             case "banner" -> { | ||||
|                 if (state instanceof Banner banner) { | ||||
|                     List<Tag> patterns = this.tag.getListTag("Patterns").getValue(); | ||||
|                     if (patterns == null || patterns.isEmpty()) { | ||||
|                         return false; | ||||
|                     } | ||||
|                     banner.setPatterns(patterns.stream().map(t -> (CompoundTag) t).map(compoundTag -> { | ||||
|                         DyeColor color = DyeColor.getByWoolData((byte) compoundTag.getInt("Color")); | ||||
|                         PatternType patternType = PatternType.getByIdentifier(compoundTag.getString("Pattern")); | ||||
|                         if (color == null || patternType == null) { | ||||
|                             return null; | ||||
|                         } | ||||
|                         return new Pattern(color, patternType); | ||||
|                     }).filter(Objects::nonNull).toList()); | ||||
|                     banner.update(true); | ||||
|                     return true; | ||||
|                 } | ||||
|                 return false; | ||||
|   | ||||
| @@ -70,7 +70,7 @@ public class BukkitRegionManager extends RegionManager { | ||||
|     @Inject | ||||
|     public BukkitRegionManager( | ||||
|             @NonNull WorldUtil worldUtil, @NonNull GlobalBlockQueue blockQueue, @NonNull | ||||
|     ProgressSubscriberFactory subscriberFactory | ||||
|             ProgressSubscriberFactory subscriberFactory | ||||
|     ) { | ||||
|         super(worldUtil, blockQueue, subscriberFactory); | ||||
|         this.blockQueue = blockQueue; | ||||
|   | ||||
| @@ -124,7 +124,7 @@ public class BukkitSetupUtils extends SetupUtils { | ||||
|     public String setupWorld(PlotAreaBuilder builder) { | ||||
|         this.updateGenerators(false); | ||||
|         ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ? | ||||
|                 new ConfigurationNode[0] : builder.settingsNodesWrapper().settingsNodes(); | ||||
|                 new ConfigurationNode[0] : builder.settingsNodesWrapper().getSettingsNodes(); | ||||
|         String world = builder.worldName(); | ||||
|         PlotAreaType type = builder.plotAreaType(); | ||||
|         String worldPath = "worlds." + builder.worldName(); | ||||
|   | ||||
| @@ -28,32 +28,24 @@ import java.nio.file.Paths; | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| /** | ||||
|  * This is a helper class which replaces older syntax no longer supported by MiniMessage with replacements in messages_%.json. | ||||
|  * This is a helper class which replaces occurrences of 'suggest_command' with 'run_command' in messages_%.json. | ||||
|  * MiniMessage changed the syntax between major releases. To warrant a smooth upgrade, we attempt to replace any occurrences | ||||
|  * while loading PlotSquared. | ||||
|  * | ||||
|  * @since 7.0.0 | ||||
|  * @since TODO | ||||
|  */ | ||||
| @NotPublic | ||||
| public class TranslationUpdateManager { | ||||
|  | ||||
|     public static void upgradeTranslationFile() throws IOException { | ||||
|         String suggestCommand = "suggest_command"; | ||||
|         String suggestCommandReplacement = "run_command"; | ||||
|         String minHeight = "minHeight"; | ||||
|         String minheightReplacement = "minheight"; | ||||
|         String maxHeight = "maxHeight"; | ||||
|         String maxheightReplacement = "maxheight"; | ||||
|         String searchText = "suggest_command"; | ||||
|         String replacementText = "run_command"; | ||||
|  | ||||
|         try (Stream<Path> paths = Files.walk(Paths.get(PlotSquared.platform().getDirectory().toPath().resolve("lang").toUri()))) { | ||||
|             paths | ||||
|                     .filter(Files::isRegularFile) | ||||
|                     .filter(p -> p.getFileName().toString().matches("messages_[a-z]{2}\\.json")) | ||||
|                     .forEach(p -> { | ||||
|                         replaceInFile(p, suggestCommand, suggestCommandReplacement); | ||||
|                         replaceInFile(p, minHeight, minheightReplacement); | ||||
|                         replaceInFile(p, maxHeight, maxheightReplacement); | ||||
|                     }); | ||||
|                     .forEach(p -> replaceInFile(p, searchText, replacementText)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -68,5 +60,4 @@ public class TranslationUpdateManager { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -54,8 +54,7 @@ public class UpdateUtility implements Listener { | ||||
|         internalVersion = PlotSquared.get().getVersion(); | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings({"deprecation", "DefaultCharset"}) | ||||
|     // Suppress Json deprecation, we can't use features from gson 2.8.1 and newer yet | ||||
|     @SuppressWarnings({"deprecation", "DefaultCharset"}) // Suppress Json deprecation, we can't use features from gson 2.8.1 and newer yet | ||||
|     public void updateChecker() { | ||||
|         task = Bukkit.getScheduler().runTaskTimerAsynchronously(this.javaPlugin, () -> { | ||||
|             try { | ||||
|   | ||||
| @@ -111,8 +111,8 @@ public class SQLiteUUIDService implements UUIDService, Consumer<List<UUIDMapping | ||||
|         try (final PreparedStatement statement = getConnection() | ||||
|                 .prepareStatement("INSERT OR REPLACE INTO `usercache` (`uuid`, `username`) VALUES(?, ?)")) { | ||||
|             for (final UUIDMapping mapping : uuidWrappers) { | ||||
|                 statement.setString(1, mapping.uuid().toString()); | ||||
|                 statement.setString(2, mapping.username()); | ||||
|                 statement.setString(1, mapping.getUuid().toString()); | ||||
|                 statement.setString(2, mapping.getUsername()); | ||||
|                 statement.executeUpdate(); | ||||
|             } | ||||
|         } catch (SQLException e) { | ||||
|   | ||||
| @@ -4,16 +4,16 @@ api-version: "1.13" | ||||
| version: "${version}" | ||||
| load: STARTUP | ||||
| description: "Easy, yet powerful Plot World generation and management." | ||||
| authors: [ Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell ] | ||||
| authors: [Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell] | ||||
| website: https://www.spigotmc.org/resources/77506/ | ||||
| softdepend: [ Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms, MVdWPlaceholderAPI ] | ||||
| loadbefore: [ MultiWorld, Multiverse-Core ] | ||||
| depend: [ WorldEdit ] | ||||
| softdepend: [Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms, MVdWPlaceholderAPI] | ||||
| loadbefore: [MultiWorld, Multiverse-Core] | ||||
| depend: [WorldEdit] | ||||
| database: false | ||||
| commands: | ||||
|   plots: | ||||
|     description: Plot command. | ||||
|     aliases: [ p,plot,ps,plotsquared,p2,2,plotme ] | ||||
|     aliases: [p,plot,ps,plotsquared,p2,2,plotme] | ||||
|     permission: plots.use | ||||
|     permission-message: "You are lacking the permission node 'plots.use'" | ||||
| permissions: | ||||
|   | ||||
| @@ -23,13 +23,13 @@ include: | ||||
| Examples of unacceptable behavior by participants include: | ||||
|  | ||||
| * The use of sexualized language or imagery and unwelcome sexual attention or | ||||
|   advances | ||||
|  advances | ||||
| * Trolling, insulting/derogatory comments, and personal or political attacks | ||||
| * Public or private harassment | ||||
| * Publishing others' private information, such as a physical or electronic | ||||
|   address, without explicit permission | ||||
|  address, without explicit permission | ||||
| * Other conduct which could reasonably be considered inappropriate in a | ||||
|   professional setting | ||||
|  professional setting | ||||
|  | ||||
| ## Our Responsibilities | ||||
|  | ||||
| @@ -55,7 +55,7 @@ further defined and clarified by project maintainers. | ||||
| ## Enforcement | ||||
|  | ||||
| Instances of abusive, harassing, or otherwise unacceptable behavior may be | ||||
| reported by contacting the project team at contact<at>intellectualsites.com. All | ||||
| reported by contacting the project team at contact@intellectualsites.com. All | ||||
| complaints will be reviewed and investigated and will result in a response that | ||||
| is deemed necessary and appropriate to the circumstances. The project team is | ||||
| obligated to maintain confidentiality with regard to the reporter of an incident. | ||||
|   | ||||
| @@ -15,6 +15,11 @@ dependencies { | ||||
|     api("net.kyori:adventure-api") | ||||
|     api("net.kyori:adventure-text-minimessage") | ||||
|  | ||||
|     // Cloud | ||||
|     api(libs.cloudServices) | ||||
|     api(libs.cloudCore) | ||||
|     api(libs.cloudAnnotations) | ||||
|  | ||||
|     // Guice | ||||
|     api(libs.guice) { | ||||
|         exclude(group = "com.google.guava") | ||||
| @@ -40,7 +45,6 @@ dependencies { | ||||
|     // Other libraries | ||||
|     api(libs.prtree) | ||||
|     api(libs.aopalliance) | ||||
|     api(libs.cloudServices) | ||||
|     api(libs.arkitektonika) | ||||
|     api("com.intellectualsites.paster:Paster") | ||||
|     api("com.intellectualsites.informative-annotations:informative-annotations") | ||||
| @@ -68,8 +72,8 @@ tasks { | ||||
|         val isRelease = if (rootProject.version.toString().endsWith("-SNAPSHOT")) "TODO" else rootProject.version.toString() | ||||
|         val opt = options as StandardJavadocDocletOptions | ||||
|         opt.links("https://docs.enginehub.org/javadoc/com.sk89q.worldedit/worldedit-core/" + libs.worldeditCore.get().versionConstraint.toString()) | ||||
|         opt.links("https://jd.advntr.dev/api/4.14.0/") | ||||
|         opt.links("https://jd.advntr.dev/text-minimessage/4.14.0/") | ||||
|         opt.links("https://jd.adventure.kyori.net/api/4.12.0/") | ||||
|         opt.links("https://jd.adventure.kyori.net/text-minimessage/4.12.0/") | ||||
|         opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/") | ||||
|         opt.links("https://checkerframework.org/api/") | ||||
|         opt.links("https://javadoc.io/doc/com.intellectualsites.informative-annotations/informative-annotations/latest/") | ||||
|   | ||||
| @@ -270,11 +270,7 @@ public class PlotSquared { | ||||
|             captionMap = this.captionLoader.loadAll(this.platform.getDirectory().toPath().resolve("lang")); | ||||
|         } else { | ||||
|             String fileName = "messages_" + Settings.Enabled_Components.DEFAULT_LOCALE + ".json"; | ||||
|             captionMap = this.captionLoader.loadOrCreateSingle(this.platform | ||||
|                     .getDirectory() | ||||
|                     .toPath() | ||||
|                     .resolve("lang") | ||||
|                     .resolve(fileName)); | ||||
|             captionMap = this.captionLoader.loadOrCreateSingle(this.platform.getDirectory().toPath().resolve("lang").resolve(fileName)); | ||||
|         } | ||||
|         this.captionMaps.put(TranslatableCaption.DEFAULT_NAMESPACE, captionMap); | ||||
|         LOGGER.info( | ||||
| @@ -1015,7 +1011,7 @@ public class PlotSquared { | ||||
|  | ||||
|     /** | ||||
|      * Setup the configuration for a plot world based on world arguments. | ||||
|      * <p> | ||||
|      * | ||||
|      * | ||||
|      * <i>e.g. /mv create <world> normal -g PlotSquared:<args></i> | ||||
|      * | ||||
|   | ||||
| @@ -136,9 +136,13 @@ public class SimpleBackupManager implements BackupManager { | ||||
|         return this.backupLimit; | ||||
|     } | ||||
|  | ||||
|     private record PlotCacheKey( | ||||
|             Plot plot | ||||
|     ) { | ||||
|     private static final class PlotCacheKey { | ||||
|  | ||||
|         private final Plot plot; | ||||
|  | ||||
|         private PlotCacheKey(Plot plot) { | ||||
|             this.plot = plot; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean equals(final Object o) { | ||||
|   | ||||
| @@ -1,173 +0,0 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.command; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.util.PlayerManager; | ||||
| import com.plotsquared.core.util.TabCompletions; | ||||
| import com.plotsquared.core.util.task.RunnableVal2; | ||||
| import com.plotsquared.core.util.task.RunnableVal3; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.Iterator; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.TimeoutException; | ||||
|  | ||||
| @CommandDeclaration(command = "add", | ||||
|         usage = "/plot add <player | *>", | ||||
|         category = CommandCategory.SETTINGS, | ||||
|         permission = "plots.add", | ||||
|         requiredType = RequiredType.PLAYER) | ||||
| public class Add extends Command { | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     public Add(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         super(MainCommand.getInstance(), true); | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public CompletableFuture<Boolean> execute( | ||||
|             final PlotPlayer<?> player, | ||||
|             String[] args, | ||||
|             RunnableVal3<Command, Runnable, Runnable> confirm, | ||||
|             RunnableVal2<Command, CommandResult> whenDone | ||||
|     ) throws CommandException { | ||||
|         final Plot plot = check(player.getCurrentPlot(), TranslatableCaption.of("errors.not_in_plot")); | ||||
|         checkTrue(plot.hasOwner(), TranslatableCaption.of("info.plot_unowned")); | ||||
|         checkTrue( | ||||
|                 plot.isOwner(player.getUUID()) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST), | ||||
|                 TranslatableCaption.of("permission.no_plot_perms") | ||||
|         ); | ||||
|         checkTrue( | ||||
|                 args.length == 1, | ||||
|                 TranslatableCaption.of("commandconfig.command_syntax"), | ||||
|                 TagResolver.resolver("value", Tag.inserting(Component.text("/plot add <player | *>"))) | ||||
|         ); | ||||
|         final CompletableFuture<Boolean> future = new CompletableFuture<>(); | ||||
|         PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> { | ||||
|             if (throwable != null) { | ||||
|                 if (throwable instanceof TimeoutException) { | ||||
|                     player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("errors.invalid_player"), | ||||
|                             TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) | ||||
|                     ); | ||||
|                 } | ||||
|                 future.completeExceptionally(throwable); | ||||
|                 return; | ||||
|             } else { | ||||
|                 try { | ||||
|                     checkTrue(!uuids.isEmpty(), TranslatableCaption.of("errors.invalid_player"), | ||||
|                             TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) | ||||
|                     ); | ||||
|                     Iterator<UUID> iterator = uuids.iterator(); | ||||
|                     int size = plot.getTrusted().size() + plot.getMembers().size(); | ||||
|                     while (iterator.hasNext()) { | ||||
|                         UUID uuid = iterator.next(); | ||||
|                         if (uuid == DBFunc.EVERYONE && !(player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission( | ||||
|                                 Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { | ||||
|                             player.sendMessage( | ||||
|                                     TranslatableCaption.of("errors.invalid_player"), | ||||
|                                     TagResolver.resolver("value", Tag.inserting( | ||||
|                                             PlayerManager.resolveName(uuid).toComponent(player) | ||||
|                                     )) | ||||
|                             ); | ||||
|                             iterator.remove(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         if (plot.isOwner(uuid)) { | ||||
|                             player.sendMessage( | ||||
|                                     TranslatableCaption.of("member.already_added"), | ||||
|                                     TagResolver.resolver("player", Tag.inserting( | ||||
|                                             PlayerManager.resolveName(uuid).toComponent(player) | ||||
|                                     )) | ||||
|                             ); | ||||
|                             iterator.remove(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         if (plot.getMembers().contains(uuid)) { | ||||
|                             player.sendMessage( | ||||
|                                     TranslatableCaption.of("member.already_added"), | ||||
|                                     TagResolver.resolver("player", Tag.inserting( | ||||
|                                             PlayerManager.resolveName(uuid).toComponent(player) | ||||
|                                     )) | ||||
|                             ); | ||||
|                             iterator.remove(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         size += plot.getTrusted().contains(uuid) ? 0 : 1; | ||||
|                     } | ||||
|                     checkTrue(!uuids.isEmpty(), null); | ||||
|                     int localAddSize = plot.getMembers().size(); | ||||
|                     int maxAddSize = player.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS); | ||||
|                     if (localAddSize >= maxAddSize) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("members.plot_max_members_added"), | ||||
|                                 TagResolver.resolver("amount", Tag.inserting(Component.text(localAddSize))) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                     // Success | ||||
|                     confirm.run(this, () -> { | ||||
|                         for (UUID uuid : uuids) { | ||||
|                             if (uuid != DBFunc.EVERYONE) { | ||||
|                                 if (!plot.removeTrusted(uuid)) { | ||||
|                                     if (plot.getDenied().contains(uuid)) { | ||||
|                                         plot.removeDenied(uuid); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             plot.addMember(uuid); | ||||
|                             this.eventDispatcher.callMember(player, plot, uuid, true); | ||||
|                             player.sendMessage(TranslatableCaption.of("member.member_added")); | ||||
|                         } | ||||
|                     }, null); | ||||
|                 } catch (final Throwable exception) { | ||||
|                     future.completeExceptionally(exception); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             future.complete(true); | ||||
|         }); | ||||
|         return future; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { | ||||
|         return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,210 +0,0 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.command; | ||||
|  | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.query.PlotQuery; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeoutException; | ||||
|  | ||||
| @CommandDeclaration(command = "alias", | ||||
|         permission = "plots.alias", | ||||
|         usage = "/plot alias <set | remove> <alias>", | ||||
|         aliases = {"setalias", "sa", "name", "rename", "setname", "seta", "nameplot"}, | ||||
|         category = CommandCategory.SETTINGS, | ||||
|         requiredType = RequiredType.PLAYER) | ||||
| public class Alias extends SubCommand { | ||||
|  | ||||
|     private static final Command SET_COMMAND = new Command(null, false, "set", null, RequiredType.NONE, null) { | ||||
|     }; | ||||
|     private static final Command REMOVE_COMMAND = new Command(null, false, "remove", null, RequiredType.NONE, null) { | ||||
|     }; | ||||
|  | ||||
|     @Override | ||||
|     public boolean onCommand(PlotPlayer<?> player, String[] args) { | ||||
|  | ||||
|         if (args.length == 0) { | ||||
|             sendUsage(player); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         Location location = player.getLocation(); | ||||
|         Plot plot = location.getPlotAbs(); | ||||
|         if (plot == null) { | ||||
|             player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!plot.hasOwner()) { | ||||
|             player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         boolean result = false; | ||||
|  | ||||
|         boolean owner = plot.isOwner(player.getUUID()); | ||||
|         boolean permission; | ||||
|         boolean admin; | ||||
|         switch (args[0].toLowerCase()) { | ||||
|             case "set" -> { | ||||
|                 if (args.length != 2) { | ||||
|                     sendUsage(player); | ||||
|                     return false; | ||||
|                 } | ||||
|                 permission = isPermitted(player, Permission.PERMISSION_ALIAS_SET); | ||||
|                 admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_SET); | ||||
|                 if (!admin && !owner) { | ||||
|                     player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|                     return false; | ||||
|                 } | ||||
|                 if (permission) { // is either admin or owner | ||||
|                     setAlias(player, plot, args[1]); | ||||
|                     return true; | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
|                             TagResolver.resolver( | ||||
|                                     "node", | ||||
|                                     Tag.inserting(Permission.PERMISSION_ALIAS_SET) | ||||
|                             ) | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|             case "remove" -> { | ||||
|                 permission = isPermitted(player, Permission.PERMISSION_ALIAS_REMOVE); | ||||
|                 admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_REMOVE); | ||||
|                 if (!admin && !owner) { | ||||
|                     player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|                     return false; | ||||
|                 } | ||||
|                 if (permission) { | ||||
|                     result = removeAlias(player, plot); | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
|                             TagResolver.resolver( | ||||
|                                     "node", | ||||
|                                     Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE) | ||||
|                             ) | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|             default -> { | ||||
|                 sendUsage(player); | ||||
|                 result = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Collection<Command> tab(PlotPlayer<?> player, String[] args, boolean space) { | ||||
|         final List<Command> commands = new ArrayList<>(2); | ||||
|         if (args.length == 1) { | ||||
|             if ("set".startsWith(args[0])) { | ||||
|                 commands.add(SET_COMMAND); | ||||
|             } | ||||
|             if ("remove".startsWith(args[0])) { | ||||
|                 commands.add(REMOVE_COMMAND); | ||||
|             } | ||||
|             return commands; | ||||
|         } | ||||
|         return Collections.emptySet(); | ||||
|     } | ||||
|  | ||||
|     private void setAlias(PlotPlayer<?> player, Plot plot, String alias) { | ||||
|         if (alias.isEmpty()) { | ||||
|             sendUsage(player); | ||||
|         } else if (alias.length() >= 50) { | ||||
|             player.sendMessage(TranslatableCaption.of("alias.alias_too_long")); | ||||
|         } else if (MathMan.isInteger(alias)) { | ||||
|             player.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong | ||||
|         } else { | ||||
|             if (PlotQuery.newQuery().inArea(plot.getArea()) | ||||
|                     .withAlias(alias) | ||||
|                     .anyMatch()) { | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|             if (Settings.UUID.OFFLINE) { | ||||
|                 plot.setAlias(alias); | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_set_to"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|             PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { | ||||
|                 if (throwable instanceof TimeoutException) { | ||||
|                     player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|                 } else if (uuid != null) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                             TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                     ); | ||||
|                 } else { | ||||
|                     plot.setAlias(alias); | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("alias.alias_set_to"), | ||||
|                             TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                     ); | ||||
|                 } | ||||
|             })); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private boolean removeAlias(PlotPlayer<?> player, Plot plot) { | ||||
|         String alias = plot.getAlias(); | ||||
|         if (!plot.getAlias().isEmpty()) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("alias.alias_removed"), | ||||
|                     TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|             ); | ||||
|         } else { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("alias.no_alias_set") | ||||
|             ); | ||||
|         } | ||||
|         plot.setAlias(null); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     private boolean isPermitted(PlotPlayer<?> player, Permission permission) { | ||||
|         return player.hasPermission(permission); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -35,7 +35,6 @@ import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.services.plots.AutoQuery; | ||||
| import com.plotsquared.core.services.plots.AutoService; | ||||
| import com.plotsquared.core.util.EconHandler; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| @@ -296,13 +295,10 @@ public class Auto extends SubCommand { | ||||
|         } | ||||
|         if (this.econHandler != null && plotarea.useEconomy()) { | ||||
|             PlotExpression costExp = plotarea.getPrices().get("claim"); | ||||
|             PlotExpression mergeCostExp = plotarea.getPrices().get("merge"); | ||||
|             int size = sizeX * sizeZ; | ||||
|             double mergeCost = size <= 1 || mergeCostExp == null ? 0d : mergeCostExp.evaluate(size); | ||||
|             double cost = costExp.evaluate(Settings.Limit.GLOBAL ? | ||||
|                     player.getPlotCount() : | ||||
|                     player.getPlotCount(plotarea.getWorldName())); | ||||
|             cost = size * cost + mergeCost; | ||||
|             cost = (sizeX * sizeZ) * cost; | ||||
|             if (cost > 0d) { | ||||
|                 if (!this.econHandler.isSupported()) { | ||||
|                     player.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); | ||||
| @@ -330,7 +326,7 @@ public class Auto extends SubCommand { | ||||
|         } | ||||
|  | ||||
|         List<Plot> plots = this.servicePipeline | ||||
|                 .pump(new AutoQuery(player, null, sizeX, sizeZ, plotarea)) | ||||
|                 .pump(new AutoService.AutoQuery(player, null, sizeX, sizeZ, plotarea)) | ||||
|                 .through(AutoService.class) | ||||
|                 .getResult(); | ||||
|  | ||||
|   | ||||
| @@ -107,35 +107,38 @@ public class Clear extends Command { | ||||
|             } | ||||
|             BackupManager.backup(player, plot, () -> { | ||||
|                 final long start = System.currentTimeMillis(); | ||||
|                 boolean result = plot.getPlotModificationManager().clear(true, false, player, () -> TaskManager.runTask(() -> { | ||||
|                     plot.removeRunning(); | ||||
|                     // If the state changes, then mark it as no longer done | ||||
|                     if (DoneFlag.isDone(plot)) { | ||||
|                         PlotFlag<?, ?> plotFlag = | ||||
|                                 plot.getFlagContainer().getFlag(DoneFlag.class); | ||||
|                         PlotFlagRemoveEvent event = this.eventDispatcher | ||||
|                                 .callFlagRemove(plotFlag, plot); | ||||
|                         if (event.getEventResult() != Result.DENY) { | ||||
|                             plot.removeFlag(event.getFlag()); | ||||
|                 boolean result = plot.getPlotModificationManager().clear(true, false, player, () -> { | ||||
|                     plot.getPlotModificationManager().unlink(); | ||||
|                     TaskManager.runTask(() -> { | ||||
|                         plot.removeRunning(); | ||||
|                         // If the state changes, then mark it as no longer done | ||||
|                         if (DoneFlag.isDone(plot)) { | ||||
|                             PlotFlag<?, ?> plotFlag = | ||||
|                                     plot.getFlagContainer().getFlag(DoneFlag.class); | ||||
|                             PlotFlagRemoveEvent event = this.eventDispatcher | ||||
|                                     .callFlagRemove(plotFlag, plot); | ||||
|                             if (event.getEventResult() != Result.DENY) { | ||||
|                                 plot.removeFlag(event.getFlag()); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     if (!plot.getFlag(AnalysisFlag.class).isEmpty()) { | ||||
|                         PlotFlag<?, ?> plotFlag = | ||||
|                                 plot.getFlagContainer().getFlag(AnalysisFlag.class); | ||||
|                         PlotFlagRemoveEvent event = this.eventDispatcher | ||||
|                                 .callFlagRemove(plotFlag, plot); | ||||
|                         if (event.getEventResult() != Result.DENY) { | ||||
|                             plot.removeFlag(event.getFlag()); | ||||
|                         if (!plot.getFlag(AnalysisFlag.class).isEmpty()) { | ||||
|                             PlotFlag<?, ?> plotFlag = | ||||
|                                     plot.getFlagContainer().getFlag(AnalysisFlag.class); | ||||
|                             PlotFlagRemoveEvent event = this.eventDispatcher | ||||
|                                     .callFlagRemove(plotFlag, plot); | ||||
|                             if (event.getEventResult() != Result.DENY) { | ||||
|                                 plot.removeFlag(event.getFlag()); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("working.clearing_done"), | ||||
|                             TagResolver.builder() | ||||
|                                     .tag("amount", Tag.inserting(Component.text(System.currentTimeMillis() - start))) | ||||
|                                     .tag("plot", Tag.inserting(Component.text(plot.getId().toString()))) | ||||
|                                     .build() | ||||
|                     ); | ||||
|                 })); | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("working.clearing_done"), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("amount", Tag.inserting(Component.text(System.currentTimeMillis() - start))) | ||||
|                                         .tag("plot", Tag.inserting(Component.text(plot.getId().toString()))) | ||||
|                                         .build() | ||||
|                         ); | ||||
|                     }); | ||||
|                 }); | ||||
|                 if (!result) { | ||||
|                     player.sendMessage(TranslatableCaption.of("errors.wait_for_timer")); | ||||
|                 } else { | ||||
|   | ||||
| @@ -46,7 +46,6 @@ import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedList; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.TimeoutException; | ||||
| @@ -78,7 +77,8 @@ public class Cluster extends SubCommand { | ||||
|         } | ||||
|         String sub = args[0].toLowerCase(); | ||||
|         switch (sub) { | ||||
|             case "l", "list" -> { | ||||
|             case "l": | ||||
|             case "list": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_LIST)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -133,7 +133,8 @@ public class Cluster extends SubCommand { | ||||
|                 } | ||||
|                 return true; | ||||
|             } | ||||
|             case "c", "create" -> { | ||||
|             case "c": | ||||
|             case "create": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_CREATE)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -268,7 +269,9 @@ public class Cluster extends SubCommand { | ||||
|                 ); | ||||
|                 return true; | ||||
|             } | ||||
|             case "disband", "del", "delete" -> { | ||||
|             case "disband": | ||||
|             case "del": | ||||
|             case "delete": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_DELETE)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -327,7 +330,8 @@ public class Cluster extends SubCommand { | ||||
|                 )); | ||||
|                 return true; | ||||
|             } | ||||
|             case "res", "resize" -> { | ||||
|             case "res": | ||||
|             case "resize": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_RESIZE)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -448,7 +452,9 @@ public class Cluster extends SubCommand { | ||||
|                 player.sendMessage(TranslatableCaption.of("cluster.cluster_resized")); | ||||
|                 return true; | ||||
|             } | ||||
|             case "add", "inv", "invite" -> { | ||||
|             case "add": | ||||
|             case "inv": | ||||
|             case "invite": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_INVITE)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -517,7 +523,9 @@ public class Cluster extends SubCommand { | ||||
|                         }); | ||||
|                 return true; | ||||
|             } | ||||
|             case "k", "remove", "kick" -> { | ||||
|             case "k": | ||||
|             case "remove": | ||||
|             case "kick": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_KICK)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -597,7 +605,8 @@ public class Cluster extends SubCommand { | ||||
|                         }); | ||||
|                 return true; | ||||
|             } | ||||
|             case "quit", "leave" -> { | ||||
|             case "quit": | ||||
|             case "leave": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_LEAVE)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -658,7 +667,7 @@ public class Cluster extends SubCommand { | ||||
|                 removePlayerPlots(cluster, uuid, player.getLocation().getWorldName()); | ||||
|                 return true; | ||||
|             } | ||||
|             case "members" -> { | ||||
|             case "members": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_HELPERS)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -719,7 +728,9 @@ public class Cluster extends SubCommand { | ||||
|                         }); | ||||
|                 return true; | ||||
|             } | ||||
|             case "spawn", "home", "tp" -> { | ||||
|             case "spawn": | ||||
|             case "home": | ||||
|             case "tp": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_TP)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -767,7 +778,10 @@ public class Cluster extends SubCommand { | ||||
|                 player.sendMessage(TranslatableCaption.of("cluster.cluster_teleporting")); | ||||
|                 return true; | ||||
|             } | ||||
|             case "i", "info", "show", "information" -> { | ||||
|             case "i": | ||||
|             case "info": | ||||
|             case "show": | ||||
|             case "information": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_INFO)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
| @@ -814,7 +828,11 @@ public class Cluster extends SubCommand { | ||||
|                                 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|                             } else { | ||||
|                                 final String owner; | ||||
|                                 owner = Objects.requireNonNullElse(username, "unknown"); | ||||
|                                 if (username == null) { | ||||
|                                     owner = "unknown"; | ||||
|                                 } else { | ||||
|                                     owner = username; | ||||
|                                 } | ||||
|                                 String name = cluster.getName(); | ||||
|                                 String size = (cluster.getP2().getX() - cluster.getP1().getX() + 1) + "x" + ( | ||||
|                                         cluster.getP2().getY() - cluster.getP1().getY() + 1); | ||||
| @@ -832,7 +850,9 @@ public class Cluster extends SubCommand { | ||||
|                         }); | ||||
|                 return true; | ||||
|             } | ||||
|             case "sh", "setspawn", "sethome" -> { | ||||
|             case "sh": | ||||
|             case "setspawn": | ||||
|             case "sethome": { | ||||
|                 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_SETHOME)) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
|   | ||||
| @@ -559,10 +559,9 @@ public abstract class Command { | ||||
|  | ||||
|     public Collection<Command> tab(PlotPlayer<?> player, String[] args, boolean space) { | ||||
|         switch (args.length) { | ||||
|             case 0 -> { | ||||
|             case 0: | ||||
|                 return this.allCommands; | ||||
|             } | ||||
|             case 1 -> { | ||||
|             case 1: | ||||
|                 String arg = args[0].toLowerCase(); | ||||
|                 if (space) { | ||||
|                     Command cmd = getCommand(arg); | ||||
| @@ -581,15 +580,13 @@ public abstract class Command { | ||||
|                     } | ||||
|                     return commands; | ||||
|                 } | ||||
|             } | ||||
|             default -> { | ||||
|             default: | ||||
|                 Command cmd = getCommand(args[0]); | ||||
|                 if (cmd != null) { | ||||
|                     return cmd.tab(player, Arrays.copyOfRange(args, 1, args.length), space); | ||||
|                 } else { | ||||
|                     return null; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -69,8 +69,7 @@ public class Copy extends SubCommand { | ||||
|  | ||||
|         plot1.getPlotModificationManager().copy(plot2, player).thenAccept(result -> { | ||||
|             if (result) { | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("move.copy_success"), | ||||
|                 player.sendMessage(TranslatableCaption.of("move.copy_success"), | ||||
|                         TagResolver.builder() | ||||
|                                 .tag("origin", Tag.inserting(Component.text(plot1.toString()))) | ||||
|                                 .tag("target", Tag.inserting(Component.text(plot2.toString()))) | ||||
|   | ||||
| @@ -71,9 +71,9 @@ public class DebugPaste extends SubCommand { | ||||
|                 StringBuilder b = new StringBuilder(); | ||||
|                 b.append( | ||||
|                         """ | ||||
|                                 # Welcome to this paste | ||||
|                                 # It is meant to provide us at IntellectualSites with better information about your problem | ||||
|                                 """ | ||||
|                          # Welcome to this paste | ||||
|                          # It is meant to provide us at IntellectualSites with better information about your problem | ||||
|                          """ | ||||
|                 ); | ||||
|                 b.append("# PlotSquared Information\n"); | ||||
|                 b.append("PlotSquared Version: ").append(PlotSquared.get().getVersion()) | ||||
|   | ||||
| @@ -75,19 +75,16 @@ public class DebugRoadRegen extends SubCommand { | ||||
|         } | ||||
|         String kind = args[0].toLowerCase(); | ||||
|         switch (kind) { | ||||
|             case "plot" -> { | ||||
|             case "plot": | ||||
|                 return regenPlot(player); | ||||
|             } | ||||
|             case "region" -> { | ||||
|             case "region": | ||||
|                 return regenRegion(player, Arrays.copyOfRange(args, 1, args.length)); | ||||
|             } | ||||
|             default -> { | ||||
|             default: | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("commandconfig.command_syntax"), | ||||
|                         TagResolver.resolver("value", Tag.inserting(Component.text(DebugRoadRegen.USAGE))) | ||||
|                 ); | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -103,7 +103,7 @@ public class Done extends SubCommand { | ||||
|                 public void run(PlotAnalysis value) { | ||||
|                     plot.removeRunning(); | ||||
|                     boolean result = | ||||
|                             value.getComplexity(doneRequirements) >= doneRequirements.THRESHOLD; | ||||
|                             value.getComplexity(doneRequirements) <= doneRequirements.THRESHOLD; | ||||
|                     finish(plot, player, result); | ||||
|                 } | ||||
|             }); | ||||
|   | ||||
| @@ -185,25 +185,22 @@ public class Download extends SubCommand { | ||||
|         if (Settings.Web.LEGACY_WEBINTERFACE) { | ||||
|             schematicHandler | ||||
|                     .getCompoundTag(plot) | ||||
|                     .whenComplete((compoundTag, throwable) -> schematicHandler.upload( | ||||
|                             compoundTag, | ||||
|                             null, | ||||
|                             null, | ||||
|                             new RunnableVal<>() { | ||||
|                                 @Override | ||||
|                                 public void run(URL value) { | ||||
|                                     plot.removeRunning(); | ||||
|                                     player.sendMessage( | ||||
|                                             TranslatableCaption.of("web.generation_link_success"), | ||||
|                                             TagResolver.builder() | ||||
|                                                     .tag("download", Tag.preProcessParsed(value.toString())) | ||||
|                                                     .tag("delete", Tag.preProcessParsed("Not available")) | ||||
|                                                     .build() | ||||
|                                     ); | ||||
|                                     player.sendMessage(StaticCaption.of(value.toString())); | ||||
|                                 } | ||||
|                     .whenComplete((compoundTag, throwable) -> { | ||||
|                         schematicHandler.upload(compoundTag, null, null, new RunnableVal<>() { | ||||
|                             @Override | ||||
|                             public void run(URL value) { | ||||
|                                 plot.removeRunning(); | ||||
|                                 player.sendMessage( | ||||
|                                         TranslatableCaption.of("web.generation_link_success"), | ||||
|                                         TagResolver.builder() | ||||
|                                                 .tag("download", Tag.preProcessParsed(value.toString())) | ||||
|                                                 .tag("delete", Tag.preProcessParsed("Not available")) | ||||
|                                                 .build() | ||||
|                                 ); | ||||
|                                 player.sendMessage(StaticCaption.of(value.toString())); | ||||
|                             } | ||||
|                     )); | ||||
|                         }); | ||||
|                     }); | ||||
|             return; | ||||
|         } | ||||
|         // TODO legacy support | ||||
|   | ||||
| @@ -60,10 +60,9 @@ public class Help extends Command { | ||||
|             RunnableVal2<Command, CommandResult> whenDone | ||||
|     ) { | ||||
|         switch (args.length) { | ||||
|             case 0 -> { | ||||
|             case 0: | ||||
|                 return displayHelp(player, null, 0); | ||||
|             } | ||||
|             case 1 -> { | ||||
|             case 1: | ||||
|                 if (MathMan.isInteger(args[0])) { | ||||
|                     try { | ||||
|                         return displayHelp(player, null, Integer.parseInt(args[0])); | ||||
| @@ -73,8 +72,7 @@ public class Help extends Command { | ||||
|                 } else { | ||||
|                     return displayHelp(player, args[0], 1); | ||||
|                 } | ||||
|             } | ||||
|             case 2 -> { | ||||
|             case 2: | ||||
|                 if (MathMan.isInteger(args[1])) { | ||||
|                     try { | ||||
|                         return displayHelp(player, args[0], Integer.parseInt(args[1])); | ||||
| @@ -83,8 +81,8 @@ public class Help extends Command { | ||||
|                     } | ||||
|                 } | ||||
|                 return CompletableFuture.completedFuture(false); | ||||
|             } | ||||
|             default -> sendUsage(player); | ||||
|             default: | ||||
|                 sendUsage(player); | ||||
|         } | ||||
|         return CompletableFuture.completedFuture(true); | ||||
|     } | ||||
| @@ -134,12 +132,7 @@ public class Help extends Command { | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("command", Tag.inserting(Component.text("/plot help"))) | ||||
|                                         .tag("category", Tag.inserting(Component.text("all"))) | ||||
|                                         .tag( | ||||
|                                                 "category_desc", | ||||
|                                                 Tag.inserting(TranslatableCaption | ||||
|                                                         .of("help.help_display_all_commands") | ||||
|                                                         .toComponent(player)) | ||||
|                                         ) | ||||
|                                         .tag("category_desc", Tag.inserting(TranslatableCaption.of("help.help_display_all_commands").toComponent(player))) | ||||
|                                         .build() | ||||
|                         )); | ||||
|                 builder.append(Component.newline()).append(MINI_MESSAGE.deserialize(TranslatableCaption | ||||
|   | ||||
| @@ -85,24 +85,24 @@ public class Inbox extends SubCommand { | ||||
|         for (int x = page * 12; x < max; x++) { | ||||
|             PlotComment comment = comments[x]; | ||||
|             Component commentColored; | ||||
|             if (player.getName().equals(comment.senderName())) { | ||||
|             if (player.getName().equals(comment.senderName)) { | ||||
|                 commentColored = MINI_MESSAGE | ||||
|                         .deserialize( | ||||
|                                 TranslatableCaption.of("list.comment_list_by_lister").getComponent(player), | ||||
|                                 TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment()))) | ||||
|                                 TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment))) | ||||
|                         ); | ||||
|             } else { | ||||
|                 commentColored = MINI_MESSAGE | ||||
|                         .deserialize( | ||||
|                                 TranslatableCaption.of("list.comment_list_by_other").getComponent(player), | ||||
|                                 TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment()))) | ||||
|                                 TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment))) | ||||
|                         ); | ||||
|             } | ||||
|             TagResolver resolver = TagResolver.builder() | ||||
|                     .tag("number", Tag.inserting(Component.text(x))) | ||||
|                     .tag("world", Tag.inserting(Component.text(comment.world()))) | ||||
|                     .tag("plot_id", Tag.inserting(Component.text(comment.id().getX() + ";" + comment.id().getY()))) | ||||
|                     .tag("commenter", Tag.inserting(Component.text(comment.senderName()))) | ||||
|                     .tag("world", Tag.inserting(Component.text(comment.world))) | ||||
|                     .tag("plot_id", Tag.inserting(Component.text(comment.id.getX() + ";" + comment.id.getY()))) | ||||
|                     .tag("commenter", Tag.inserting(Component.text(comment.senderName))) | ||||
|                     .tag("comment", Tag.inserting(commentColored)) | ||||
|                     .build(); | ||||
|             builder.append(MINI_MESSAGE | ||||
| @@ -137,7 +137,7 @@ public class Inbox extends SubCommand { | ||||
|                                 int unread = 0; | ||||
|                                 for (PlotComment comment : value) { | ||||
|                                     total++; | ||||
|                                     if (comment.timestamp() > CommentManager | ||||
|                                     if (comment.timestamp > CommentManager | ||||
|                                             .getTimestamp(player, inbox.toString())) { | ||||
|                                         unread++; | ||||
|                                     } | ||||
| @@ -190,7 +190,7 @@ public class Inbox extends SubCommand { | ||||
|         final int page; | ||||
|         if (args.length > 1) { | ||||
|             switch (args[1].toLowerCase()) { | ||||
|                 case "delete" -> { | ||||
|                 case "delete": | ||||
|                     if (!inbox.canModify(plot, player)) { | ||||
|                         player.sendMessage(TranslatableCaption.of("comment.no_perm_inbox_modify")); | ||||
|                         return false; | ||||
| @@ -225,6 +225,7 @@ public class Inbox extends SubCommand { | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|  | ||||
|                     if (!inbox.getComments(plot, new RunnableVal<>() { | ||||
|                         @Override | ||||
|                         public void run(List<PlotComment> value) { | ||||
| @@ -241,7 +242,7 @@ public class Inbox extends SubCommand { | ||||
|                             if (success) { | ||||
|                                 player.sendMessage( | ||||
|                                         TranslatableCaption.of("comment.comment_removed_success"), | ||||
|                                         TagResolver.resolver("value", Tag.inserting(Component.text(comment.comment()))) | ||||
|                                         TagResolver.resolver("value", Tag.inserting(Component.text(comment.comment))) | ||||
|                                 ); | ||||
|                             } else { | ||||
|                                 player.sendMessage( | ||||
| @@ -253,8 +254,7 @@ public class Inbox extends SubCommand { | ||||
|                         return false; | ||||
|                     } | ||||
|                     return true; | ||||
|                 } | ||||
|                 case "clear" -> { | ||||
|                 case "clear": | ||||
|                     if (!inbox.canModify(plot, player)) { | ||||
|                         player.sendMessage(TranslatableCaption.of("comment.no_perm_inbox_modify")); | ||||
|                     } | ||||
| @@ -268,15 +268,13 @@ public class Inbox extends SubCommand { | ||||
|                         plot.getPlotCommentContainer().removeComments(comments); | ||||
|                     } | ||||
|                     return true; | ||||
|                 } | ||||
|                 default -> { | ||||
|                 default: | ||||
|                     try { | ||||
|                         page = Integer.parseInt(args[1]); | ||||
|                     } catch (NumberFormatException ignored) { | ||||
|                         sendUsage(player); | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             page = 1; | ||||
|   | ||||
| @@ -52,9 +52,8 @@ public class Info extends SubCommand { | ||||
|             arg = args[0]; | ||||
|             switch (arg) { | ||||
|                 // TODO: (re?)implement /plot info inv. (it was never properly implemented) | ||||
|                 case "trusted", "alias", "biome", "denied", "flags", "id", "size", "members", "creationdate", "seen", "owner", "rating", "likes" -> | ||||
|                         plot = Plot | ||||
|                                 .getPlotFromString(player, null, false); | ||||
|                 case "trusted", "alias", "biome", "denied", "flags", "id", "size", "members", "creationdate", "seen", "owner", "rating", "likes" -> plot = Plot | ||||
|                         .getPlotFromString(player, null, false); | ||||
|                 default -> { | ||||
|                     plot = Plot.getPlotFromString(player, arg, false); | ||||
|                     if (args.length == 2) { | ||||
|   | ||||
| @@ -112,15 +112,15 @@ public class Kick extends SubCommand { | ||||
|                 for (PlotPlayer<?> player2 : players) { | ||||
|                     if (!plot.equals(player2.getCurrentPlot())) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("kick.player_not_in_plot"), | ||||
|                                 TagResolver.resolver("player", Tag.inserting(Component.text(player2.getName()))) | ||||
|                                 TranslatableCaption.of("errors.invalid_player"), | ||||
|                                 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (player2.hasPermission(Permission.PERMISSION_ADMIN_ENTRY_DENIED)) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("kick.cannot_kick_player"), | ||||
|                                 TagResolver.resolver("player", Tag.inserting(Component.text(player2.getName()))) | ||||
|                                 TranslatableCaption.of("cluster.cannot_kick_player"), | ||||
|                                 TagResolver.resolver("name", Tag.inserting(Component.text(player2.getName()))) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|   | ||||
| @@ -474,20 +474,20 @@ public class ListCmd extends SubCommand { | ||||
|                         final List<UUIDMapping> names = PlotSquared.get().getImpromptuUUIDPipeline().getNames(plot.getOwners()) | ||||
|                                 .get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS); | ||||
|                         for (final UUIDMapping uuidMapping : names) { | ||||
|                             PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuidMapping.uuid()); | ||||
|                             PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuidMapping.getUuid()); | ||||
|                             TagResolver resolver = TagResolver.builder() | ||||
|                                     .tag("prefix", Tag.inserting(Component.text(prefix))) | ||||
|                                     .tag("player", Tag.inserting(Component.text(uuidMapping.username()))) | ||||
|                                     .build(); | ||||
|                             if (pp != null) { | ||||
|                                 builder.append(MINI_MESSAGE.deserialize(online, resolver)); | ||||
|                             } else if (uuidMapping.username().equalsIgnoreCase("unknown")) { | ||||
|                                 .tag("prefix", Tag.inserting(Component.text(prefix))) | ||||
|                                 .tag("player", Tag.inserting(Component.text(uuidMapping.getUsername()))) | ||||
|                                 .build(); | ||||
|                         if (pp != null) { | ||||
|                             builder.append(MINI_MESSAGE.deserialize(online, resolver)); | ||||
|                             } else if (uuidMapping.getUsername().equalsIgnoreCase("unknown")) { | ||||
|                                 TagResolver unknownResolver = TagResolver.resolver( | ||||
|                                         "info.unknown", | ||||
|                                         Tag.inserting(TranslatableCaption.of("info.unknown").toComponent(player)) | ||||
|                                 ); | ||||
|                                 builder.append(MINI_MESSAGE.deserialize(unknown, unknownResolver)); | ||||
|                             } else if (uuidMapping.uuid().equals(DBFunc.EVERYONE)) { | ||||
|                             } else if (uuidMapping.getUuid().equals(DBFunc.EVERYONE)) { | ||||
|                                 TagResolver everyoneResolver = TagResolver.resolver( | ||||
|                                         "info.everyone", | ||||
|                                         Tag.inserting(TranslatableCaption.of("info.everyone").toComponent(player)) | ||||
|   | ||||
| @@ -86,7 +86,6 @@ public class MainCommand extends Command { | ||||
|             commands.add(CreateRoadSchematic.class); | ||||
|             commands.add(DebugAllowUnsafe.class); | ||||
|             commands.add(RegenAllRoads.class); | ||||
|             commands.add(Claim.class); | ||||
|             commands.add(Auto.class); | ||||
|             commands.add(HomeCommand.class); | ||||
|             commands.add(Visit.class); | ||||
| @@ -94,7 +93,6 @@ public class MainCommand extends Command { | ||||
|             commands.add(Clear.class); | ||||
|             commands.add(Delete.class); | ||||
|             commands.add(Trust.class); | ||||
|             commands.add(Add.class); | ||||
|             commands.add(Leave.class); | ||||
|             commands.add(Deny.class); | ||||
|             commands.add(Remove.class); | ||||
| @@ -130,7 +128,6 @@ public class MainCommand extends Command { | ||||
|             commands.add(Owner.class); | ||||
|             commands.add(Desc.class); | ||||
|             commands.add(Biome.class); | ||||
|             commands.add(Alias.class); | ||||
|             commands.add(SetHome.class); | ||||
|             commands.add(Cluster.class); | ||||
|             commands.add(DebugImportWorlds.class); | ||||
|   | ||||
| @@ -56,7 +56,7 @@ public class Music extends SubCommand { | ||||
|             .asList("music_disc_13", "music_disc_cat", "music_disc_blocks", "music_disc_chirp", | ||||
|                     "music_disc_far", "music_disc_mall", "music_disc_mellohi", "music_disc_stal", | ||||
|                     "music_disc_strad", "music_disc_ward", "music_disc_11", "music_disc_wait", "music_disc_otherside", | ||||
|                     "music_disc_pigstep", "music_disc_5", "music_disc_relic" | ||||
|                     "music_disc_pigstep", "music_disc_5" | ||||
|             ); | ||||
|  | ||||
|     private final InventoryUtil inventoryUtil; | ||||
|   | ||||
| @@ -90,8 +90,12 @@ public class Purge extends SubCommand { | ||||
|                 return false; | ||||
|             } | ||||
|             switch (split[0].toLowerCase()) { | ||||
|                 case "world", "w" -> world = split[1]; | ||||
|                 case "area", "a" -> { | ||||
|                 case "world": | ||||
|                 case "w": | ||||
|                     world = split[1]; | ||||
|                     break; | ||||
|                 case "area": | ||||
|                 case "a": | ||||
|                     area = this.plotAreaManager.getPlotAreaByString(split[1]); | ||||
|                     if (area == null) { | ||||
|                         player.sendMessage( | ||||
| @@ -100,8 +104,9 @@ public class Purge extends SubCommand { | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|                 case "plotid", "id" -> { | ||||
|                     break; | ||||
|                 case "plotid": | ||||
|                 case "id": | ||||
|                     try { | ||||
|                         id = PlotId.fromString(split[1]); | ||||
|                     } catch (IllegalArgumentException ignored) { | ||||
| @@ -111,8 +116,9 @@ public class Purge extends SubCommand { | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|                 case "owner", "o" -> { | ||||
|                     break; | ||||
|                 case "owner": | ||||
|                 case "o": | ||||
|                     UUIDMapping ownerMapping = PlotSquared.get().getImpromptuUUIDPipeline().getImmediately(split[1]); | ||||
|                     if (ownerMapping == null) { | ||||
|                         player.sendMessage( | ||||
| @@ -121,9 +127,10 @@ public class Purge extends SubCommand { | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|                     owner = ownerMapping.uuid(); | ||||
|                 } | ||||
|                 case "shared", "s" -> { | ||||
|                     owner = ownerMapping.getUuid(); | ||||
|                     break; | ||||
|                 case "shared": | ||||
|                 case "s": | ||||
|                     UUIDMapping addedMapping = PlotSquared.get().getImpromptuUUIDPipeline().getImmediately(split[1]); | ||||
|                     if (addedMapping == null) { | ||||
|                         player.sendMessage( | ||||
| @@ -132,14 +139,23 @@ public class Purge extends SubCommand { | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|                     added = addedMapping.uuid(); | ||||
|                 } | ||||
|                 case "clear", "c", "delete", "d", "del" -> clear = Boolean.parseBoolean(split[1]); | ||||
|                 case "unknown", "?", "u" -> unknown = Boolean.parseBoolean(split[1]); | ||||
|                 default -> { | ||||
|                     added = addedMapping.getUuid(); | ||||
|                     break; | ||||
|                 case "clear": | ||||
|                 case "c": | ||||
|                 case "delete": | ||||
|                 case "d": | ||||
|                 case "del": | ||||
|                     clear = Boolean.parseBoolean(split[1]); | ||||
|                     break; | ||||
|                 case "unknown": | ||||
|                 case "?": | ||||
|                 case "u": | ||||
|                     unknown = Boolean.parseBoolean(split[1]); | ||||
|                     break; | ||||
|                 default: | ||||
|                     sendUsage(player); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         final HashSet<Plot> toDelete = new HashSet<>(); | ||||
| @@ -220,9 +236,9 @@ public class Purge extends SubCommand { | ||||
|                             try { | ||||
|                                 ids.add(plot.temp); | ||||
|                                 if (finalClear) { | ||||
|                                     plot.getPlotModificationManager().clear(false, true, player, | ||||
|                                             () -> LOGGER.info("Plot {} cleared by purge", plot.getId()) | ||||
|                                     ); | ||||
|                                     plot.getPlotModificationManager().clear(false, true, player, () -> { | ||||
|                                         LOGGER.info("Plot {} cleared by purge", plot.getId()); | ||||
|                                     }); | ||||
|                                 } else { | ||||
|                                     plot.getPlotModificationManager().removeSign(); | ||||
|                                 } | ||||
|   | ||||
| @@ -156,9 +156,9 @@ public class Template extends SubCommand { | ||||
|              ZipOutputStream zos = new ZipOutputStream(fos)) { | ||||
|  | ||||
|             for (FileBytes file : files) { | ||||
|                 ZipEntry ze = new ZipEntry(file.path()); | ||||
|                 ZipEntry ze = new ZipEntry(file.path); | ||||
|                 zos.putNextEntry(ze); | ||||
|                 zos.write(file.data()); | ||||
|                 zos.write(file.data); | ||||
|             } | ||||
|             zos.closeEntry(); | ||||
|         } | ||||
|   | ||||
							
								
								
									
										104
									
								
								Core/src/main/java/com/plotsquared/core/commands/CommandAdd.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Core/src/main/java/com/plotsquared/core/commands/CommandAdd.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands; | ||||
|  | ||||
| import cloud.commandframework.annotations.Argument; | ||||
| import cloud.commandframework.annotations.CommandMethod; | ||||
| import cloud.commandframework.annotations.CommandPermission; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.arguments.PlotMember; | ||||
| import com.plotsquared.core.commands.requirements.Requirement; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirement; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.util.PlayerManager; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| class CommandAdd implements PlotSquaredCommandContainer { | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     CommandAdd(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.IS_OWNER) | ||||
|     @CommandPermission("plots.add") | ||||
|     @CommandMethod("${command.prefix} add [target]") | ||||
|     public void commandAdd( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             @Argument("target") final PlotMember target, | ||||
|             final @NonNull Plot plot | ||||
|     ) { | ||||
|         if (target instanceof PlotMember.Everyone) { | ||||
|             if (!sender.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) && !sender.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST)) { | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("errors.invalid_player"), | ||||
|                         TagResolver.resolver("value", Tag.inserting( | ||||
|                                 PlayerManager.resolveName(target.uuid()).toComponent(sender) | ||||
|                         )) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|         } else if (plot.isOwner(target.uuid())) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("member.already_added"), | ||||
|                     TagResolver.resolver("player", Tag.inserting( | ||||
|                             PlayerManager.resolveName(target.uuid()).toComponent(sender) | ||||
|                     )) | ||||
|             ); | ||||
|             return; | ||||
|         } else if (plot.getMembers().contains(target.uuid())) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("member.already_added"), | ||||
|                     TagResolver.resolver("player", Tag.inserting( | ||||
|                             PlayerManager.resolveName(target.uuid()).toComponent(sender) | ||||
|                     )) | ||||
|             ); | ||||
|             return; | ||||
|         } else if (plot.getMembers().size() >= sender.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS)) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("members.plot_max_members_added"), | ||||
|                     TagResolver.resolver("amount", Tag.inserting(Component.text(plot.getMembers().size()))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (target instanceof PlotMember.Player) { | ||||
|             if (!plot.removeTrusted(target.uuid())) { | ||||
|                 if (plot.getDenied().contains(target.uuid())) { | ||||
|                     plot.removeDenied(target.uuid()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         plot.addMember(target.uuid()); | ||||
|         this.eventDispatcher.callMember(sender, plot, target.uuid(), true); | ||||
|         sender.sendMessage(TranslatableCaption.of("member.member_added")); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,136 @@ | ||||
| package com.plotsquared.core.commands; | ||||
|  | ||||
| import cloud.commandframework.annotations.Argument; | ||||
| import cloud.commandframework.annotations.CommandMethod; | ||||
| import cloud.commandframework.annotations.CommandPermission; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirement; | ||||
| import com.plotsquared.core.commands.requirements.Requirement; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.query.PlotQuery; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.concurrent.TimeoutException; | ||||
|  | ||||
| public class CommandAlias implements PlotSquaredCommandContainer { | ||||
|  | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.PLOT_HAS_OWNER) | ||||
|     @CommandPermission("plots.alias") | ||||
|     @CommandMethod("${command.prefix} alias set <alias>") | ||||
|     public void commandAliasSet( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             final @NonNull Plot plot, | ||||
|             @Argument("alias") final @NonNull String alias | ||||
|     ) { | ||||
|         final boolean isOwner = plot.isOwner(sender.getUUID()); | ||||
|  | ||||
|         if (!isOwner && !sender.hasPermission(Permission.PERMISSION_ADMIN_ALIAS_SET)) { | ||||
|             sender.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|             return; | ||||
|         } else if (!sender.hasPermission(Permission.PERMISSION_ALIAS_SET)) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("permission.no_permission"), | ||||
|                     TagResolver.resolver( | ||||
|                             "node", | ||||
|                             Tag.inserting(Permission.PERMISSION_ALIAS_SET) | ||||
|                     ) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (alias.length() >= 50) { | ||||
|             sender.sendMessage(TranslatableCaption.of("alias.alias_too_long")); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (MathMan.isInteger(alias)) { | ||||
|             sender.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (PlotQuery.newQuery().inArea(plot.getArea()) | ||||
|                 .withAlias(alias) | ||||
|                 .anyMatch()) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                     TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (Settings.UUID.OFFLINE) { | ||||
|             plot.setAlias(alias); | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("alias.alias_set_to"), | ||||
|                     TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { | ||||
|             if (throwable instanceof TimeoutException) { | ||||
|                 sender.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|             } else if (uuid != null) { | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|             } else { | ||||
|                 plot.setAlias(alias); | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_set_to"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|             } | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.PLOT_HAS_OWNER) | ||||
|     @CommandPermission("plots.alias") | ||||
|     @CommandMethod("${command.prefix} alias remove") | ||||
|     public void commandAliasRemove( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             final @NonNull Plot plot | ||||
|     ) { | ||||
|         final boolean isOwner = plot.isOwner(sender.getUUID()); | ||||
|  | ||||
|         if (!isOwner && !sender.hasPermission(Permission.PERMISSION_ADMIN_ALIAS_REMOVE)) { | ||||
|             sender.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|             return; | ||||
|         } else if (!sender.hasPermission(Permission.PERMISSION_ALIAS_REMOVE)) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("permission.no_permission"), | ||||
|                     TagResolver.resolver( | ||||
|                             "node", | ||||
|                             Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE) | ||||
|                     ) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (plot.getAlias().isEmpty()) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("alias.no_alias_set") | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final String currentAlias = plot.getAlias(); | ||||
|         plot.setAlias(null); | ||||
|  | ||||
|         sender.sendMessage( | ||||
|                 TranslatableCaption.of("alias.alias_removed"), | ||||
|                 TagResolver.resolver("alias", Tag.inserting(Component.text(currentAlias))) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,24 +1,11 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.command; | ||||
| package com.plotsquared.core.commands; | ||||
| 
 | ||||
| import cloud.commandframework.annotations.Argument; | ||||
| import cloud.commandframework.annotations.CommandMethod; | ||||
| import cloud.commandframework.annotations.CommandPermission; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirement; | ||||
| import com.plotsquared.core.commands.requirements.Requirement; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| @@ -26,7 +13,6 @@ import com.plotsquared.core.events.PlayerClaimPlotEvent; | ||||
| import com.plotsquared.core.events.PlotMergeEvent; | ||||
| import com.plotsquared.core.events.Result; | ||||
| import com.plotsquared.core.location.Direction; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.MetaDataAccess; | ||||
| import com.plotsquared.core.player.PlayerMetaDataKeys; | ||||
| @@ -43,22 +29,17 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| 
 | ||||
| @CommandDeclaration( | ||||
|         command = "claim", | ||||
|         aliases = "c", | ||||
|         category = CommandCategory.CLAIMING, | ||||
|         requiredType = RequiredType.PLAYER, permission = "plots.claim", | ||||
|         usage = "/plot claim") | ||||
| public class Claim extends SubCommand { | ||||
| public class CommandClaim implements PlotSquaredCommandContainer { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Claim.class.getSimpleName()); | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + CommandClaim.class.getSimpleName()); | ||||
| 
 | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|     private final EconHandler econHandler; | ||||
| 
 | ||||
|     @Inject | ||||
|     public Claim( | ||||
|     CommandClaim( | ||||
|             final @NonNull EventDispatcher eventDispatcher, | ||||
|             final @NonNull EconHandler econHandler | ||||
|     ) { | ||||
| @@ -66,124 +47,132 @@ public class Claim extends SubCommand { | ||||
|         this.econHandler = econHandler; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean onCommand(final PlotPlayer<?> player, String[] args) { | ||||
|         String schematic = null; | ||||
|         if (args.length >= 1) { | ||||
|             schematic = args[0]; | ||||
|         } | ||||
|         Location location = player.getLocation(); | ||||
|         Plot plot = location.getPlotAbs(); | ||||
|         if (plot == null) { | ||||
|             player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); | ||||
|             return false; | ||||
|         } | ||||
|         final PlayerClaimPlotEvent event = this.eventDispatcher.callClaim(player, plot, schematic); | ||||
|         schematic = event.getSchematic(); | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.IN_PLOT) | ||||
|     @CommandPermission("plots.add") | ||||
|     @CommandMethod("${command.prefix} claim [schematic]") | ||||
|     public void commandClaim( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             final @NonNull Plot plot, | ||||
|             @Argument("schematic") final @Nullable String schematic | ||||
|     ) { | ||||
|         final PlayerClaimPlotEvent event = this.eventDispatcher.callClaim(sender, plot, schematic); | ||||
|         if (event.getEventResult() == Result.DENY) { | ||||
|             player.sendMessage( | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("events.event_denied"), | ||||
|                     TagResolver.resolver("value", Tag.inserting(Component.text("Claim"))) | ||||
|             ); | ||||
|             return true; | ||||
|             return; | ||||
|         } | ||||
|         boolean force = event.getEventResult() == Result.FORCE; | ||||
|         int currentPlots = Settings.Limit.GLOBAL ? | ||||
|                 player.getPlotCount() : | ||||
|                 player.getPlotCount(location.getWorldName()); | ||||
| 
 | ||||
|         final boolean forceClaim = event.getEventResult() == Result.FORCE; | ||||
|         final int currentPlots = Settings.Limit.GLOBAL ? | ||||
|                 sender.getPlotCount() : | ||||
|                 sender.getPlotCount(sender.getLocation().getWorldName()); | ||||
|         final PlotArea area = plot.getArea(); | ||||
| 
 | ||||
|         try (final MetaDataAccess<Integer> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { | ||||
|         try (final MetaDataAccess<Integer> metaDataAccess = sender.accessPersistentMetaData( | ||||
|                 PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS | ||||
|         )) { | ||||
|             int grants = 0; | ||||
|             if (currentPlots >= player.getAllowedPlots() && !force) { | ||||
|             if (currentPlots >= sender.getAllowedPlots() && !forceClaim) { | ||||
|                 if (metaDataAccess.isPresent()) { | ||||
|                     grants = metaDataAccess.get().orElse(0); | ||||
|                     if (grants <= 0) { | ||||
|                         player.sendMessage( | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.cant_claim_more_plots"), | ||||
|                                 TagResolver.resolver("amount", Tag.inserting(Component.text(grants))) | ||||
|                         ); | ||||
|                         metaDataAccess.remove(); | ||||
|                     } | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                     sender.sendMessage( | ||||
|                             TranslatableCaption.of("permission.cant_claim_more_plots"), | ||||
|                             TagResolver.resolver("amount", Tag.inserting(Component.text(player.getAllowedPlots()))) | ||||
|                             TagResolver.resolver("amount", Tag.inserting(Component.text(sender.getAllowedPlots()))) | ||||
|                     ); | ||||
|                     return false; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!plot.canClaim(player)) { | ||||
|                 player.sendMessage(TranslatableCaption.of("working.plot_is_claimed")); | ||||
|                 return false; | ||||
|             if (!plot.canClaim(sender)) { | ||||
|                 sender.sendMessage(TranslatableCaption.of("working.plot_is_claimed")); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (schematic != null && !schematic.isEmpty()) { | ||||
|                 if (area.isSchematicClaimSpecify()) { | ||||
|                     if (!area.hasSchematic(schematic)) { | ||||
|                         player.sendMessage( | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("schematics.schematic_invalid_named"), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("schemname", Tag.inserting(Component.text(schematic))) | ||||
|                                         .tag("reason", Tag.inserting(Component.text("non-existent"))) | ||||
|                                         .build() | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (!player.hasPermission(Permission.PERMISSION_CLAIM_SCHEMATIC | ||||
|                             .format(schematic)) && !player.hasPermission( | ||||
| 
 | ||||
|                     if (!sender.hasPermission( | ||||
|                             Permission.PERMISSION_CLAIM_SCHEMATIC.format(schematic) | ||||
|                     ) && !sender.hasPermission( | ||||
|                             "plots.admin.command.schematic" | ||||
|                     ) && !force) { | ||||
|                         player.sendMessage( | ||||
|                     ) && !forceClaim) { | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.no_schematic_permission"), | ||||
|                                 TagResolver.resolver("value", Tag.inserting(Component.text(schematic))) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (this.econHandler.isEnabled(area) && !force) { | ||||
|                 PlotExpression costExr = area.getPrices().get("claim"); | ||||
|                 double cost = costExr.evaluate(currentPlots); | ||||
| 
 | ||||
|             if (this.econHandler.isEnabled(area) && !forceClaim) { | ||||
|                 final PlotExpression costExr = area.getPrices().get("claim"); | ||||
|                 final double cost = costExr.evaluate(currentPlots); | ||||
| 
 | ||||
|                 if (cost > 0d) { | ||||
|                     if (!this.econHandler.isSupported()) { | ||||
|                         player.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); | ||||
|                         return false; | ||||
|                         sender.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (this.econHandler.getMoney(player) < cost) { | ||||
|                         player.sendMessage( | ||||
|                     if (this.econHandler.getMoney(sender) < cost) { | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("economy.cannot_afford_plot"), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("money", Tag.inserting(Component.text(this.econHandler.format(cost)))) | ||||
|                                         .tag( | ||||
|                                                 "balance", | ||||
|                                                 Tag.inserting(Component.text(this.econHandler.format(this.econHandler.getMoney( | ||||
|                                                         player)))) | ||||
|                                                 Tag.inserting( | ||||
|                                                         Component.text(this.econHandler.format(this.econHandler.getMoney(sender))) | ||||
|                                                 ) | ||||
|                                         ) | ||||
|                                         .build() | ||||
|                         ); | ||||
|                         return false; | ||||
|                         return; | ||||
|                     } | ||||
|                     this.econHandler.withdrawMoney(player, cost); | ||||
|                     player.sendMessage( | ||||
|                     this.econHandler.withdrawMoney(sender, cost); | ||||
|                     sender.sendMessage( | ||||
|                             TranslatableCaption.of("economy.removed_balance"), | ||||
|                             TagResolver.builder() | ||||
|                                     .tag("money", Tag.inserting(Component.text(this.econHandler.format(cost)))) | ||||
|                                     .tag( | ||||
|                                             "balance", | ||||
|                                             Tag.inserting(Component.text(this.econHandler.format(this.econHandler.getMoney( | ||||
|                                                     player)))) | ||||
|                                             Tag.inserting( | ||||
|                                                     Component.text(this.econHandler.format(this.econHandler.getMoney(sender))) | ||||
|                                             ) | ||||
|                                     ) | ||||
|                                     .build() | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (grants > 0) { | ||||
|                 if (grants == 1) { | ||||
|                     metaDataAccess.remove(); | ||||
|                 } else { | ||||
|                     metaDataAccess.set(grants - 1); | ||||
|                 } | ||||
|                 player.sendMessage( | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("economy.removed_granted_plot"), | ||||
|                         TagResolver.builder() | ||||
|                                 .tag("usedGrants", Tag.inserting(Component.text(grants - 1))) | ||||
| @@ -192,27 +181,34 @@ public class Claim extends SubCommand { | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         if (!player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { | ||||
|             int border = area.getBorder(); | ||||
|             if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !force) { | ||||
|                 player.sendMessage(TranslatableCaption.of("border.denied")); | ||||
|                 return false; | ||||
| 
 | ||||
|         if (!sender.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { | ||||
|             final int border = area.getBorder(); | ||||
|             if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !forceClaim) { | ||||
|                 sender.sendMessage(TranslatableCaption.of("border.denied")); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         plot.setOwnerAbs(player.getUUID()); | ||||
|         final String finalSchematic = schematic; | ||||
| 
 | ||||
|         // Actually update the owner :) | ||||
|         plot.setOwnerAbs(sender.getUUID()); | ||||
| 
 | ||||
|         DBFunc.createPlotSafe(plot, () -> { | ||||
|             try { | ||||
|                 TaskManager.getPlatformImplementation().sync(() -> { | ||||
|                     if (!plot.claim(player, true, finalSchematic, false, false)) { | ||||
|                     if (!plot.claim(sender, true, event.getSchematic(), false, false)) { | ||||
|                         LOGGER.info("Failed to claim plot {}", plot.getId().toCommaSeparatedString()); | ||||
|                         player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|                         sender.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|                         plot.setOwnerAbs(null); | ||||
|                     } else if (area.isAutoMerge()) { | ||||
|                         PlotMergeEvent mergeEvent = Claim.this.eventDispatcher | ||||
|                                 .callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); | ||||
|                         final PlotMergeEvent mergeEvent = this.eventDispatcher.callMerge( | ||||
|                                 plot, | ||||
|                                 Direction.ALL, | ||||
|                                 Integer.MAX_VALUE, | ||||
|                                 sender | ||||
|                         ); | ||||
|                         if (mergeEvent.getEventResult() == Result.DENY) { | ||||
|                             player.sendMessage( | ||||
|                             sender.sendMessage( | ||||
|                                     TranslatableCaption.of("events.event_denied"), | ||||
|                                     TagResolver.resolver("value", Tag.inserting(Component.text("Auto merge on claim"))) | ||||
|                             ); | ||||
| @@ -220,11 +216,11 @@ public class Claim extends SubCommand { | ||||
|                             if (plot.getPlotModificationManager().autoMerge( | ||||
|                                     mergeEvent.getDir(), | ||||
|                                     mergeEvent.getMax(), | ||||
|                                     player.getUUID(), | ||||
|                                     player, | ||||
|                                     sender.getUUID(), | ||||
|                                     sender, | ||||
|                                     true | ||||
|                             )) { | ||||
|                                 eventDispatcher.callPostMerge(player, plot); | ||||
|                                 eventDispatcher.callPostMerge(sender, plot); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| @@ -235,10 +231,8 @@ public class Claim extends SubCommand { | ||||
|             } | ||||
|         }, () -> { | ||||
|             LOGGER.info("Failed to add plot to database: {}", plot.getId().toCommaSeparatedString()); | ||||
|             player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|             sender.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|             plot.setOwnerAbs(null); | ||||
|         }); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands; | ||||
|  | ||||
| import cloud.commandframework.captions.Caption; | ||||
|  | ||||
| public final class PlotSquaredCaptionKeys { | ||||
|  | ||||
|     public static final Caption ARGUMENT_PARSE_FAILURE_TARGET = Caption.of("argument.parse.failure.target"); | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands; | ||||
|  | ||||
| /** | ||||
|  * Indicates that a class contains commands. | ||||
|  */ | ||||
| public interface PlotSquaredCommandContainer { | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands; | ||||
|  | ||||
| import cloud.commandframework.CommandManager; | ||||
| import cloud.commandframework.annotations.AnnotationParser; | ||||
| import cloud.commandframework.meta.SimpleCommandMeta; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Injector; | ||||
| import com.plotsquared.core.commands.parsers.PlotMemberParser; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirementBuilderModifier; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirementPostProcessor; | ||||
| import com.plotsquared.core.commands.requirements.Requirements; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| public class PlotSquaredCommandManager { | ||||
|  | ||||
|     private final Injector injector; | ||||
|     private final CommandManager<PlotPlayer<?>> commandManager; | ||||
|     private final AnnotationParser<PlotPlayer<?>> annotationParser; | ||||
|  | ||||
|     @Inject | ||||
|     public PlotSquaredCommandManager( | ||||
|             final @NonNull Injector injector, | ||||
|             final @NonNull CommandManager<PlotPlayer<?>> commandManager | ||||
|     ) { | ||||
|         this.injector = injector; | ||||
|         this.commandManager = commandManager; | ||||
|         this.annotationParser = new AnnotationParser<PlotPlayer<?>>( | ||||
|                 this.commandManager, | ||||
|                 new TypeToken<PlotPlayer<?>>() { | ||||
|                 }, | ||||
|                 parameters -> SimpleCommandMeta.empty() | ||||
|         ); | ||||
|         this.annotationParser.registerBuilderModifier(Requirements.class, new CommandRequirementBuilderModifier()); | ||||
|         this.commandManager.registerCommandPostProcessor(new CommandRequirementPostProcessor()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Scans the given {@code instance} for commands, and registers them. | ||||
|      * | ||||
|      * @param instance the instance to scan | ||||
|      */ | ||||
|     public void scanClass(final @NonNull Object instance) { | ||||
|         this.annotationParser.parse(instance); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Initializes all the known commands. | ||||
|      */ | ||||
|     public void initializeCommands() { | ||||
|         // We start by scanning the parsers. | ||||
|         Stream.of( | ||||
|                 PlotMemberParser.class | ||||
|         ).map(this.injector::getInstance).forEach(this::scanClass); | ||||
|         // Then we scan the commands. | ||||
|         Stream.of( | ||||
|                 CommandAdd.class, | ||||
|                 CommandClaim.class | ||||
|         ).map(this.injector::getInstance).forEach(this::scanClass); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands.arguments; | ||||
|  | ||||
| import cloud.commandframework.context.CommandContext; | ||||
| import com.plotsquared.core.commands.parsers.PlotMemberParser; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.MonotonicNonNull; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import java.util.UUID; | ||||
|  | ||||
| public sealed interface PlotMember { | ||||
|  | ||||
|     PlotMember EVERYONE = new Everyone(); | ||||
|  | ||||
|     default @NonNull UUID uuid(@NonNull CommandContext<PlotPlayer<?>> context) { | ||||
|         return this.uuid(); | ||||
|     } | ||||
|  | ||||
|     @NonNull UUID uuid(); | ||||
|  | ||||
|     sealed interface PlayerLike extends PlotMember { | ||||
|     } | ||||
|  | ||||
|     record Player(@NonNull UUID uuid) implements PlayerLike { | ||||
|     } | ||||
|  | ||||
|     final class LazyPlayer implements PlayerLike { | ||||
|  | ||||
|         private final String candidate; | ||||
|         private final UuidSupplier uuidSupplier; | ||||
|         private @MonotonicNonNull UUID cachedUuid = null; | ||||
|  | ||||
|         public LazyPlayer( | ||||
|                 final @NonNull String candidate, | ||||
|                 final @NonNull UuidSupplier uuidSupplier | ||||
|         ) { | ||||
|             this.candidate = candidate; | ||||
|             this.uuidSupplier = uuidSupplier; | ||||
|         } | ||||
|  | ||||
|         public @NonNull UUID uuid() { | ||||
|             throw new UnsupportedOperationException(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public synchronized @NonNull UUID uuid(final @NonNull CommandContext<PlotPlayer<?>> context) { | ||||
|             if (this.cachedUuid == null) { | ||||
|                 try { | ||||
|                     this.cachedUuid = this.uuidSupplier.uuid(); | ||||
|                 } catch (Exception ignored) { | ||||
|                 } | ||||
|  | ||||
|                 // The player didn't exist :-( | ||||
|                 if (this.cachedUuid == null) { | ||||
|                     throw new PlotMemberParser.TargetParseException(this.candidate, context); | ||||
|                 } | ||||
|             } | ||||
|             return this.cachedUuid; | ||||
|         } | ||||
|  | ||||
|         @FunctionalInterface | ||||
|         public interface UuidSupplier { | ||||
|             @Nullable UUID uuid() throws Exception; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     final class Everyone implements PlotMember { | ||||
|  | ||||
|         @Override | ||||
|         public @NonNull UUID uuid() { | ||||
|             return DBFunc.EVERYONE; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,124 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands.parsers; | ||||
|  | ||||
| import cloud.commandframework.annotations.parsers.Parser; | ||||
| import cloud.commandframework.captions.CaptionVariable; | ||||
| import cloud.commandframework.context.CommandContext; | ||||
| import cloud.commandframework.exceptions.parsing.NoInputProvidedException; | ||||
| import cloud.commandframework.exceptions.parsing.ParserException; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.PlotSquaredCaptionKeys; | ||||
| import com.plotsquared.core.commands.arguments.PlotMember; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.inject.annotations.ImpromptuPipeline; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.uuid.UUIDMapping; | ||||
| import com.plotsquared.core.uuid.UUIDPipeline; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.util.Queue; | ||||
| import java.util.UUID; | ||||
|  | ||||
| public class PlotMemberParser { | ||||
|  | ||||
|     private final UUIDPipeline uuidPipeline; | ||||
|  | ||||
|     @Inject | ||||
|     public PlotMemberParser(@ImpromptuPipeline final @NonNull UUIDPipeline uuidPipeline) { | ||||
|         this.uuidPipeline = uuidPipeline; | ||||
|     } | ||||
|  | ||||
|     @Parser | ||||
|     public @NonNull PlotMember parse( | ||||
|             final @NonNull CommandContext<PlotPlayer<?>> context, | ||||
|             final @NonNull Queue<@NonNull String> input | ||||
|     ) { | ||||
|         final var candidate = input.peek(); | ||||
|         if (candidate == null) { | ||||
|             throw new NoInputProvidedException(this.getClass(), context); | ||||
|         } | ||||
|  | ||||
|         if ("*".equals(candidate)) { | ||||
|             return PlotMember.EVERYONE; | ||||
|         } else if (candidate.length() > 16) { | ||||
|             try { | ||||
|                 return new PlotMember.Player(UUID.fromString(candidate)); | ||||
|             } catch (IllegalArgumentException ignored) { | ||||
|                 throw new TargetParseException(candidate, context); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (Settings.Paper_Components.PAPER_LISTENERS) { | ||||
|             try { | ||||
|                 return this.uuidPipeline.getUUID(candidate, Settings.UUID.NON_BLOCKING_TIMEOUT) | ||||
|                         .get() | ||||
|                         .map(UUIDMapping::getUuid) | ||||
|                         .map(PlotMember.Player::new) | ||||
|                         .orElseThrow(); | ||||
|             } catch (Exception e) { | ||||
|                 throw new TargetParseException(candidate, context); | ||||
|             } | ||||
|         } else { | ||||
|             return new PlotMember.LazyPlayer( | ||||
|                     candidate, | ||||
|                     () -> this.uuidPipeline.getUUID(candidate, Settings.UUID.NON_BLOCKING_TIMEOUT) | ||||
|                             .get() | ||||
|                             .map(UUIDMapping::getUuid) | ||||
|                             .orElse(null) | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static final class TargetParseException extends ParserException { | ||||
|  | ||||
|         @Serial | ||||
|         private static final long serialVersionUID = 927476591631527552L; | ||||
|         private final String input; | ||||
|  | ||||
|         /** | ||||
|          * Construct a new Player parse exception | ||||
|          * | ||||
|          * @param input   String input | ||||
|          * @param context Command context | ||||
|          */ | ||||
|         public TargetParseException( | ||||
|                 final @NonNull String input, | ||||
|                 final @NonNull CommandContext<?> context | ||||
|         ) { | ||||
|             super( | ||||
|                     PlotMemberParser.class, | ||||
|                     context, | ||||
|                     PlotSquaredCaptionKeys.ARGUMENT_PARSE_FAILURE_TARGET, | ||||
|                     CaptionVariable.of("input", input) | ||||
|             ); | ||||
|             this.input = input; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get the supplied input | ||||
|          * | ||||
|          * @return String value | ||||
|          */ | ||||
|         public @NonNull String getInput() { | ||||
|             return this.input; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,88 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands.requirements; | ||||
|  | ||||
| import cloud.commandframework.meta.CommandMeta; | ||||
| import com.plotsquared.core.configuration.caption.Caption; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.ConsolePlayer; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.EnumSet; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.Set; | ||||
| import java.util.function.Predicate; | ||||
|  | ||||
| public enum CommandRequirement { | ||||
|     PLAYER( | ||||
|             "", | ||||
|             player -> !(player instanceof ConsolePlayer) | ||||
|     ), | ||||
|     IN_PLOT( | ||||
|             "errors.not_in_plot", | ||||
|             player -> player.getCurrentPlot() != null | ||||
|     ), | ||||
|     PLOT_HAS_OWNER( | ||||
|             "info.plot_unowned", | ||||
|             player -> Objects.requireNonNull(player.getCurrentPlot()).hasOwner(), | ||||
|             IN_PLOT | ||||
|     ), | ||||
|     IS_OWNER( | ||||
|             "permission.no_plot_perms", | ||||
|             player -> Objects.requireNonNull(player.getCurrentPlot()).isOwner(player.getUUID()), | ||||
|             PLOT_HAS_OWNER | ||||
|     ); | ||||
|  | ||||
|     public static final CommandMeta.Key<List<CommandRequirement>> COMMAND_REQUIREMENTS_KEY = CommandMeta.Key.of( | ||||
|             new TypeToken<List<CommandRequirement>>() { | ||||
|             }, | ||||
|             "command_requirements" | ||||
|     ); | ||||
|  | ||||
|     private final @NonNull Caption caption; | ||||
|     private final @NonNull Predicate<@NonNull PlotPlayer<?>> requirementPredicate; | ||||
|     private final @NonNull Set<@NonNull CommandRequirement> inheritedRequirements; | ||||
|  | ||||
|     CommandRequirement( | ||||
|             final @NonNull String caption, | ||||
|             final @NonNull Predicate<@NonNull PlotPlayer<?>> requirementPredicate, | ||||
|             final @NonNull CommandRequirement... inheritedRequirements | ||||
|     ) { | ||||
|         this.caption = TranslatableCaption.of(caption); | ||||
|         this.requirementPredicate = requirementPredicate; | ||||
|         this.inheritedRequirements = EnumSet.copyOf(Arrays.asList(inheritedRequirements)); | ||||
|     } | ||||
|  | ||||
|     public @NonNull Set<@NonNull CommandRequirement> inheritedRequirements() { | ||||
|         return Collections.unmodifiableSet(this.inheritedRequirements); | ||||
|     } | ||||
|  | ||||
|     public @NonNull Caption caption() { | ||||
|         return this.caption; | ||||
|     } | ||||
|  | ||||
|     public boolean checkRequirement(final @NonNull PlotPlayer<?> player) { | ||||
|         return this.requirementPredicate.test(player); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,61 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands.requirements; | ||||
|  | ||||
| import cloud.commandframework.Command; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.EnumSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.function.BiFunction; | ||||
|  | ||||
| public class CommandRequirementBuilderModifier implements BiFunction< | ||||
|         @NonNull Requirements, | ||||
|         Command.@NonNull Builder<PlotPlayer<?>>, | ||||
|         Command.@NonNull Builder<PlotPlayer<?>> | ||||
| > { | ||||
|  | ||||
|     @Override | ||||
|     public Command.@NonNull Builder<PlotPlayer<?>> apply( | ||||
|             final @NonNull Requirements requirements, | ||||
|             final Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ) { | ||||
|         // We use a list, because we want them to be evaluated in order. | ||||
|         final Set<CommandRequirement> commandRequirements = EnumSet.noneOf(CommandRequirement.class); | ||||
|         for (final Requirement requirement : requirements.value()) { | ||||
|             this.addRequirements(commandRequirements, requirement.value()); | ||||
|         } | ||||
|         // We then sort the requirements. | ||||
|         final List<CommandRequirement> sortedRequirements = commandRequirements.stream().sorted().toList(); | ||||
|         // We then register all the types in the command metadata. | ||||
|         return builder.meta(CommandRequirement.COMMAND_REQUIREMENTS_KEY, sortedRequirements); | ||||
|     } | ||||
|  | ||||
|     private void addRequirements( | ||||
|             final @NonNull Set<@NonNull CommandRequirement> requirements, | ||||
|             final @NonNull CommandRequirement requirement | ||||
|     ) { | ||||
|         for (final CommandRequirement inheritedRequirement : requirement.inheritedRequirements()) { | ||||
|             addRequirements(requirements, inheritedRequirement); | ||||
|         } | ||||
|         requirements.add(requirement); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands.requirements; | ||||
|  | ||||
| import cloud.commandframework.Command; | ||||
| import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext; | ||||
| import cloud.commandframework.execution.postprocessor.CommandPostprocessor; | ||||
| import cloud.commandframework.services.types.ConsumerService; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public class CommandRequirementPostProcessor implements CommandPostprocessor<PlotPlayer<?>> { | ||||
|  | ||||
|     @Override | ||||
|     public void accept( | ||||
|             @NonNull final CommandPostprocessingContext<PlotPlayer<?>> context | ||||
|     ) { | ||||
|         final Command<PlotPlayer<?>> command = context.getCommand(); | ||||
|         final PlotPlayer<?> player = context.getCommandContext().getSender();; | ||||
|         final List<CommandRequirement> commandRequirements = command.getCommandMeta().get( | ||||
|                 CommandRequirement.COMMAND_REQUIREMENTS_KEY | ||||
|         ).orElse(List.of()); | ||||
|  | ||||
|         for (final CommandRequirement requirement : commandRequirements) { | ||||
|             if (requirement.checkRequirement(player)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // They failed the requirement =( | ||||
|             player.sendMessage(requirement.caption()); | ||||
|  | ||||
|             // Then we interrupt to make sure the command isn't executed. | ||||
|             ConsumerService.interrupt(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -16,24 +16,20 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.plot.flag.implementations; | ||||
| package com.plotsquared.core.commands.requirements; | ||||
| 
 | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.plot.flag.types.BooleanFlag; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| 
 | ||||
| public class SculkSensorInteractFlag extends BooleanFlag<SculkSensorInteractFlag> { | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Repeatable; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
| 
 | ||||
|     public static final SculkSensorInteractFlag SCULK_SENSOR_INTERACT_TRUE = new SculkSensorInteractFlag(true); | ||||
|     public static final SculkSensorInteractFlag SCULK_SENSOR_INTERACT_FALSE = new SculkSensorInteractFlag(false); | ||||
| 
 | ||||
|     private SculkSensorInteractFlag(boolean value) { | ||||
|         super(value, TranslatableCaption.of("flags.flag_description_sculk_sensor_interact")); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected SculkSensorInteractFlag flagOf(@NonNull Boolean value) { | ||||
|         return value ? SCULK_SENSOR_INTERACT_TRUE : SCULK_SENSOR_INTERACT_FALSE; | ||||
|     } | ||||
| @Repeatable(Requirements.class) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target(ElementType.METHOD) | ||||
| public @interface Requirement { | ||||
| 
 | ||||
|     @NonNull CommandRequirement value(); | ||||
| } | ||||
| @@ -0,0 +1,33 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 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 General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.commands.requirements; | ||||
|  | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
|  | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target(ElementType.METHOD) | ||||
| public @interface Requirements { | ||||
|  | ||||
|     @NonNull Requirement @NonNull[] value(); | ||||
| } | ||||
| @@ -35,22 +35,34 @@ import java.util.Map; | ||||
|  * the component GUI | ||||
|  */ | ||||
| @SerializableAs("preset") | ||||
| public record ComponentPreset( | ||||
|         ClassicPlotManagerComponent component, | ||||
|         String pattern, | ||||
|         double cost, | ||||
|         String permission, | ||||
|         String displayName, | ||||
|         List<String> description, | ||||
|         ItemType icon | ||||
| ) implements ConfigurationSerializable { | ||||
| public class ComponentPreset implements ConfigurationSerializable { | ||||
|  | ||||
|     private final ClassicPlotManagerComponent component; | ||||
|     private final String pattern; | ||||
|     private final double cost; | ||||
|     private final String permission; | ||||
|     private final String displayName; | ||||
|     private final List<String> description; | ||||
|     private final ItemType icon; | ||||
|  | ||||
|     public ComponentPreset( | ||||
|             ClassicPlotManagerComponent component, String pattern, double cost, | ||||
|             String permission, String displayName, List<String> description, final ItemType icon | ||||
|     ) { | ||||
|         this.component = component; | ||||
|         this.pattern = pattern; | ||||
|         this.cost = cost; | ||||
|         this.permission = permission; | ||||
|         this.displayName = displayName; | ||||
|         this.description = description; | ||||
|         this.icon = icon; | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static ComponentPreset deserialize(final @NonNull Map<String, Object> map) { | ||||
|         final ClassicPlotManagerComponent classicPlotManagerComponent = ClassicPlotManagerComponent | ||||
|                 .fromString(map.getOrDefault("component", "").toString()).orElseThrow(() -> | ||||
|                         new IllegalArgumentException("The preset in components.yml needs a valid target component, got: " + map.get( | ||||
|                                 "component"))); | ||||
|                         new IllegalArgumentException("The preset in components.yml needs a valid target component, got: " + map.get("component"))); | ||||
|         final String pattern = map.getOrDefault("pattern", "").toString(); | ||||
|         final double cost = Double.parseDouble(map.getOrDefault("cost", "0.0").toString()); | ||||
|         final String permission = map.getOrDefault("permission", "").toString(); | ||||
| @@ -62,6 +74,34 @@ public record ComponentPreset( | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public ClassicPlotManagerComponent getComponent() { | ||||
|         return this.component; | ||||
|     } | ||||
|  | ||||
|     public String getPattern() { | ||||
|         return this.pattern; | ||||
|     } | ||||
|  | ||||
|     public double getCost() { | ||||
|         return this.cost; | ||||
|     } | ||||
|  | ||||
|     public String getPermission() { | ||||
|         return this.permission; | ||||
|     } | ||||
|  | ||||
|     public String getDisplayName() { | ||||
|         return this.displayName; | ||||
|     } | ||||
|  | ||||
|     public List<String> getDescription() { | ||||
|         return this.description; | ||||
|     } | ||||
|  | ||||
|     public ItemType getIcon() { | ||||
|         return this.icon; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Map<String, Object> serialize() { | ||||
|         final Map<String, Object> map = new HashMap<>(); | ||||
|   | ||||
| @@ -165,8 +165,8 @@ public class ComponentPresetManager { | ||||
|  | ||||
|         final List<ComponentPreset> allowedPresets = new ArrayList<>(this.presets.size()); | ||||
|         for (final ComponentPreset componentPreset : this.presets) { | ||||
|             if (!componentPreset.permission().isEmpty() && !player.hasPermission( | ||||
|                     componentPreset.permission() | ||||
|             if (!componentPreset.getPermission().isEmpty() && !player.hasPermission( | ||||
|                     componentPreset.getPermission() | ||||
|             )) { | ||||
|                 continue; | ||||
|             } | ||||
| @@ -200,30 +200,30 @@ public class ComponentPresetManager { | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 final Pattern pattern = PatternUtil.parse(null, componentPreset.pattern(), false); | ||||
|                 final Pattern pattern = PatternUtil.parse(null, componentPreset.getPattern(), false); | ||||
|                 if (pattern == null) { | ||||
|                     getPlayer().sendMessage(TranslatableCaption.of("preset.preset_invalid")); | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 if (componentPreset.cost() > 0.0D) { | ||||
|                 if (componentPreset.getCost() > 0.0D) { | ||||
|                     if (!econHandler.isEnabled(plot.getArea())) { | ||||
|                         getPlayer().sendMessage( | ||||
|                                 TranslatableCaption.of("preset.economy_disabled"), | ||||
|                                 TagResolver.resolver("preset", Tag.inserting(Component.text(componentPreset.displayName()))) | ||||
|                                 TagResolver.resolver("preset", Tag.inserting(Component.text(componentPreset.getDisplayName()))) | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|                     if (econHandler.getMoney(getPlayer()) < componentPreset.cost()) { | ||||
|                     if (econHandler.getMoney(getPlayer()) < componentPreset.getCost()) { | ||||
|                         getPlayer().sendMessage(TranslatableCaption.of("preset.preset_cannot_afford")); | ||||
|                         return false; | ||||
|                     } else { | ||||
|                         econHandler.withdrawMoney(getPlayer(), componentPreset.cost()); | ||||
|                         econHandler.withdrawMoney(getPlayer(), componentPreset.getCost()); | ||||
|                         getPlayer().sendMessage( | ||||
|                                 TranslatableCaption.of("economy.removed_balance"), | ||||
|                                 TagResolver.resolver( | ||||
|                                         "money", | ||||
|                                         Tag.inserting(Component.text(econHandler.format(componentPreset.cost()))) | ||||
|                                         Tag.inserting(Component.text(econHandler.format(componentPreset.getCost()))) | ||||
|                                 ) | ||||
|                         ); | ||||
|                     } | ||||
| @@ -235,7 +235,7 @@ public class ComponentPresetManager { | ||||
|                     queue.setCompleteTask(plot::removeRunning); | ||||
|                     for (Plot current : plot.getConnectedPlots()) { | ||||
|                         current.getPlotModificationManager().setComponent( | ||||
|                                 componentPreset.component().name(), | ||||
|                                 componentPreset.getComponent().name(), | ||||
|                                 pattern, | ||||
|                                 player, | ||||
|                                 queue | ||||
| @@ -252,32 +252,32 @@ public class ComponentPresetManager { | ||||
|         for (int i = 0; i < allowedPresets.size(); i++) { | ||||
|             final ComponentPreset preset = allowedPresets.get(i); | ||||
|             final List<String> lore = new ArrayList<>(); | ||||
|             if (preset.cost() > 0) { | ||||
|             if (preset.getCost() > 0) { | ||||
|                 if (!this.econHandler.isEnabled(plot.getArea())) { | ||||
|                     lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize( | ||||
|                             TranslatableCaption.of("preset.preset_lore_economy_disabled").getComponent(player)))); | ||||
|                 } else { | ||||
|                     lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize( | ||||
|                             TranslatableCaption.of("preset.preset_lore_cost").getComponent(player), | ||||
|                             TagResolver.resolver("cost", Tag.inserting(Component.text(String.format("%.2f", preset.cost())))) | ||||
|                             TagResolver.resolver("cost", Tag.inserting(Component.text(String.format("%.2f", preset.getCost())))) | ||||
|                     ))); | ||||
|                 } | ||||
|             } | ||||
|             lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize( | ||||
|                     TranslatableCaption.of("preset.preset_lore_component").getComponent(player), | ||||
|                     TagResolver.builder() | ||||
|                             .tag("component", Tag.inserting(Component.text(preset.component().name().toLowerCase()))) | ||||
|                             .tag("component", Tag.inserting(Component.text(preset.getComponent().name().toLowerCase()))) | ||||
|                             .tag("prefix", Tag.inserting(TranslatableCaption.of("core.prefix").toComponent(player))) | ||||
|                             .build() | ||||
|             ))); | ||||
|             lore.removeIf(String::isEmpty); | ||||
|             lore.addAll(preset.description()); | ||||
|             lore.addAll(preset.getDescription()); | ||||
|             plotInventory.setItem( | ||||
|                     i, | ||||
|                     new PlotItemStack( | ||||
|                             preset.icon().getId().replace("minecraft:", ""), | ||||
|                             preset.getIcon().getId().replace("minecraft:", ""), | ||||
|                             1, | ||||
|                             preset.displayName(), | ||||
|                             preset.getDisplayName(), | ||||
|                             lore.toArray(new String[0]) | ||||
|                     ) | ||||
|             ); | ||||
|   | ||||
| @@ -42,6 +42,32 @@ public class Config { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Config.class.getSimpleName()); | ||||
|  | ||||
|     /** | ||||
|      * Get the value for a node<br> | ||||
|      * Probably throws some error if you try to get a non existent key | ||||
|      * | ||||
|      * @param key  configuration key | ||||
|      * @param root configuration class | ||||
|      * @param <T>  value type | ||||
|      * @return value | ||||
|      */ | ||||
|     @SuppressWarnings("unchecked") | ||||
|     public static <T> T get(String key, Class<?> root) { | ||||
|         String[] split = key.split("\\."); | ||||
|         Object instance = getInstance(split, root); | ||||
|         if (instance != null) { | ||||
|             Field field = getField(split, instance); | ||||
|             if (field != null) { | ||||
|                 try { | ||||
|                     return (T) field.get(instance); | ||||
|                 } catch (IllegalAccessException e) { | ||||
|                     e.printStackTrace(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the value of a specific node<br> | ||||
|      * Probably throws some error if you supply non existing keys or invalid values | ||||
| @@ -233,6 +259,7 @@ public class Config { | ||||
|      * | ||||
|      * @param split    the node (split by period) | ||||
|      * @param instance the instance | ||||
|      * @return | ||||
|      */ | ||||
|     private static Field getField(String[] split, Object instance) { | ||||
|         try { | ||||
| @@ -418,6 +445,10 @@ public class Config { | ||||
|             return INSTANCES.values(); | ||||
|         } | ||||
|  | ||||
|         public Collection<String> getSections() { | ||||
|             return INSTANCES.keySet(); | ||||
|         } | ||||
|  | ||||
|         private Map<String, T> getRaw() { | ||||
|             return INSTANCES; | ||||
|         } | ||||
|   | ||||
| @@ -40,7 +40,7 @@ public interface Caption { | ||||
|      * | ||||
|      * @param localeHolder Locale holder | ||||
|      * @return {@link ComponentLike} | ||||
|      * @since 7.0.0 | ||||
|      * @since TODO | ||||
|      */ | ||||
|     @NonNull Component toComponent(@NonNull LocaleHolder localeHolder); | ||||
|  | ||||
|   | ||||
| @@ -51,7 +51,7 @@ public class CaptionHolder { | ||||
|      * Get the {@link TagResolver}s to use when resolving tags in the {@link Caption}. | ||||
|      * | ||||
|      * @return The tag resolvers to use. | ||||
|      * @since 7.0.0 | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public TagResolver[] getTagResolvers() { | ||||
|         return this.tagResolvers; | ||||
| @@ -61,7 +61,7 @@ public class CaptionHolder { | ||||
|      * Set the {@link TagResolver}s to use when resolving tags in the {@link Caption}. | ||||
|      * | ||||
|      * @param tagResolvers The tag resolvers to use. | ||||
|      * @since 7.0.0 | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public void setTagResolvers(TagResolver... tagResolvers) { | ||||
|         this.tagResolvers = tagResolvers; | ||||
|   | ||||
| @@ -28,20 +28,16 @@ import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.event.ClickEvent; | ||||
| import net.kyori.adventure.text.minimessage.MiniMessage; | ||||
| import net.kyori.adventure.text.minimessage.ParsingException; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import java.util.Set; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| import static com.plotsquared.core.configuration.caption.ComponentTransform.nested; | ||||
| import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks; | ||||
|  | ||||
| public class CaptionUtility { | ||||
|  | ||||
|     private static final Pattern LEGACY_FORMATTING = Pattern.compile("§[a-gklmnor0-9]"); | ||||
|  | ||||
|     // flags which values are parsed by minimessage | ||||
|     private static final Set<Class<? extends PlotFlag<?, ?>>> MINI_MESSAGE_FLAGS = Set.of( | ||||
|             GreetingFlag.class, | ||||
| @@ -104,14 +100,7 @@ public class CaptionUtility { | ||||
|      */ | ||||
|     public static String stripClickEvents(final @NonNull String miniMessageString) { | ||||
|         // parse, transform and serialize again | ||||
|         Component component; | ||||
|         try { | ||||
|             component = MiniMessage.miniMessage().deserialize(miniMessageString); | ||||
|         } catch (ParsingException e) { | ||||
|             // if the String cannot be parsed, we try stripping legacy colors | ||||
|             String legacyStripped = LEGACY_FORMATTING.matcher(miniMessageString).replaceAll(""); | ||||
|             component = MiniMessage.miniMessage().deserialize(legacyStripped); | ||||
|         } | ||||
|         Component component = MiniMessage.miniMessage().deserialize(miniMessageString); | ||||
|         component = CLICK_STRIP_TRANSFORM.transform(component); | ||||
|         return MiniMessage.miniMessage().serialize(component); | ||||
|     } | ||||
|   | ||||
| @@ -225,7 +225,7 @@ public final class CaptionLoader { | ||||
|      */ | ||||
|     public @NonNull CaptionMap loadOrCreateSingle(final @NonNull Path file) throws IOException { | ||||
|         final Locale locale = this.localeExtractor.apply(file); | ||||
|         if (!Files.exists(file)) { | ||||
|         if (!Files.exists(file) ) { | ||||
|             Map<String, String> map = new LinkedHashMap<>(); | ||||
|             patch(map, locale); | ||||
|             save(file, map); | ||||
|   | ||||
| @@ -56,8 +56,7 @@ final class ClassLoaderCaptionProvider implements DefaultCaptionProvider { | ||||
|                 LOGGER.info("No resource for locale '{}' found in the plugin file." + | ||||
|                                 "Please ensure you have placed the latest version of the file messages_{}.json in the 'lang' folder." + | ||||
|                                 "You may be able to find completed translations at https://intellectualsites.crowdin.com/plotsquared", | ||||
|                         locale, locale | ||||
|                 ); | ||||
|                         locale, locale); | ||||
|                 return null; | ||||
|             } | ||||
|             try (final BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { | ||||
|   | ||||
| @@ -19,7 +19,6 @@ | ||||
| package com.plotsquared.core.configuration.file; | ||||
|  | ||||
| import com.plotsquared.core.configuration.serialization.ConfigurationSerialization; | ||||
| import org.yaml.snakeyaml.LoaderOptions; | ||||
| import org.yaml.snakeyaml.constructor.SafeConstructor; | ||||
| import org.yaml.snakeyaml.error.YAMLException; | ||||
| import org.yaml.snakeyaml.nodes.Node; | ||||
| @@ -31,7 +30,6 @@ import java.util.Map; | ||||
| public class YamlConstructor extends SafeConstructor { | ||||
|  | ||||
|     YamlConstructor() { | ||||
|         super(new LoaderOptions()); | ||||
|         yamlConstructors.put(Tag.MAP, new ConstructCustomObject()); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,6 @@ package com.plotsquared.core.configuration.file; | ||||
| import com.plotsquared.core.configuration.ConfigurationSection; | ||||
| import com.plotsquared.core.configuration.serialization.ConfigurationSerializable; | ||||
| import com.plotsquared.core.configuration.serialization.ConfigurationSerialization; | ||||
| import org.yaml.snakeyaml.DumperOptions; | ||||
| import org.yaml.snakeyaml.nodes.Node; | ||||
| import org.yaml.snakeyaml.representer.Representer; | ||||
|  | ||||
| @@ -31,7 +30,6 @@ import java.util.Map; | ||||
| class YamlRepresenter extends Representer { | ||||
|  | ||||
|     YamlRepresenter() { | ||||
|         super(new DumperOptions()); | ||||
|         this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection()); | ||||
|         this.multiRepresenters | ||||
|                 .put(ConfigurationSerializable.class, new RepresentConfigurationSerializable()); | ||||
|   | ||||
| @@ -2400,13 +2400,13 @@ public class SQLManager implements AbstractDB { | ||||
|                 if (plot != null) { | ||||
|                     statement.setString(1, plot.getArea().toString()); | ||||
|                     statement.setInt(2, plot.getId().hashCode()); | ||||
|                     statement.setString(3, comment.comment()); | ||||
|                     statement.setString(4, comment.inbox()); | ||||
|                     statement.setString(5, comment.senderName()); | ||||
|                     statement.setString(3, comment.comment); | ||||
|                     statement.setString(4, comment.inbox); | ||||
|                     statement.setString(5, comment.senderName); | ||||
|                 } else { | ||||
|                     statement.setString(1, comment.comment()); | ||||
|                     statement.setString(2, comment.inbox()); | ||||
|                     statement.setString(3, comment.senderName()); | ||||
|                     statement.setString(1, comment.comment); | ||||
|                     statement.setString(2, comment.inbox); | ||||
|                     statement.setString(3, comment.senderName); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -2518,10 +2518,10 @@ public class SQLManager implements AbstractDB { | ||||
|             public void set(PreparedStatement statement) throws SQLException { | ||||
|                 statement.setString(1, plot.getArea().toString()); | ||||
|                 statement.setInt(2, plot.getId().hashCode()); | ||||
|                 statement.setString(3, comment.comment()); | ||||
|                 statement.setString(4, comment.inbox()); | ||||
|                 statement.setInt(5, (int) (comment.timestamp() / 1000)); | ||||
|                 statement.setString(6, comment.senderName()); | ||||
|                 statement.setString(3, comment.comment); | ||||
|                 statement.setString(4, comment.inbox); | ||||
|                 statement.setInt(5, (int) (comment.timestamp / 1000)); | ||||
|                 statement.setString(6, comment.senderName); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
| @@ -3414,10 +3414,15 @@ public class SQLManager implements AbstractDB { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private record LegacySettings( | ||||
|             int id, | ||||
|             PlotSettings settings | ||||
|     ) { | ||||
|     private static class LegacySettings { | ||||
|  | ||||
|         public final int id; | ||||
|         public final PlotSettings settings; | ||||
|  | ||||
|         public LegacySettings(int id, PlotSettings settings) { | ||||
|             this.id = id; | ||||
|             this.settings = settings; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import com.sk89q.worldedit.entity.Entity; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| /** | ||||
|  * @since 6.11.1 | ||||
|  * @since TODO | ||||
|  */ | ||||
| public abstract class EntityEvent { | ||||
|  | ||||
| @@ -53,8 +53,7 @@ public abstract class EntityEvent { | ||||
|      * @return the event class name | ||||
|      * @since 6.11.0 | ||||
|      */ | ||||
|     @NonNull | ||||
|     public String getEventName() { | ||||
|     @NonNull public String getEventName() { | ||||
|         if (this.name == null) { | ||||
|             this.name = this.getClass().getSimpleName(); | ||||
|         } | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.events; | ||||
|  | ||||
| import com.plotsquared.core.command.Claim; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.events; | ||||
|  | ||||
| import com.plotsquared.core.command.Claim; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|   | ||||
| @@ -379,11 +379,10 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         int yStart = classicPlotWorld.getMinBuildHeight() + (classicPlotWorld.PLOT_BEDROCK ? 1 : 0); | ||||
|         if (!plot.isMerged(Direction.NORTH)) { | ||||
|             int z = bot.getZ(); | ||||
|             for (int x = bot.getX(); x < top.getX(); x++) { | ||||
|                 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -391,7 +390,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.WEST)) { | ||||
|             int x = bot.getX(); | ||||
|             for (int z = bot.getZ(); z < top.getZ(); z++) { | ||||
|                 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -399,7 +398,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.SOUTH)) { | ||||
|             int z = top.getZ(); | ||||
|             for (int x = bot.getX(); x < top.getX() + (plot.isMerged(Direction.EAST) ? 0 : 1); x++) { | ||||
|                 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -407,7 +406,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.EAST)) { | ||||
|             int x = top.getX(); | ||||
|             for (int z = bot.getZ(); z < top.getZ() + (plot.isMerged(Direction.SOUTH) ? 0 : 1); z++) { | ||||
|                 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -38,7 +38,6 @@ import javax.annotation.Nullable; | ||||
|  | ||||
| @SuppressWarnings("WeakerAccess") | ||||
| public abstract class ClassicPlotWorld extends SquarePlotWorld { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + ClassicPlotWorld.class.getSimpleName()); | ||||
|  | ||||
|     public int ROAD_HEIGHT = 62; | ||||
| @@ -65,21 +64,6 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld { | ||||
|         super(worldName, id, generator, min, max, worldConfiguration, blockQueue); | ||||
|     } | ||||
|  | ||||
|     private static BlockBucket createCheckedBlockBucket(String input, BlockBucket def) { | ||||
|         final BlockBucket bucket = new BlockBucket(input); | ||||
|         Pattern pattern = null; | ||||
|         try { | ||||
|             pattern = bucket.toPattern(); | ||||
|         } catch (Exception ignore) { | ||||
|         } | ||||
|         if (pattern == null) { | ||||
|             LOGGER.error("Failed to parse pattern '{}', check your worlds.yml", input); | ||||
|             LOGGER.error("Falling back to {}", def); | ||||
|             return def; | ||||
|         } | ||||
|         return bucket; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * CONFIG NODE | DEFAULT VALUE | DESCRIPTION | CONFIGURATION TYPE | REQUIRED FOR INITIAL SETUP. | ||||
|      * | ||||
| @@ -160,4 +144,19 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld { | ||||
|         return Math.min(WALL_HEIGHT, plotRoadMin); | ||||
|     } | ||||
|  | ||||
|     private static BlockBucket createCheckedBlockBucket(String input, BlockBucket def) { | ||||
|         final BlockBucket bucket = new BlockBucket(input); | ||||
|         Pattern pattern = null; | ||||
|         try { | ||||
|             pattern = bucket.toPattern(); | ||||
|         } catch (Exception ignore) { | ||||
|         } | ||||
|         if (pattern == null) { | ||||
|             LOGGER.error("Failed to parse pattern '{}', check your worlds.yml", input); | ||||
|             LOGGER.error("Falling back to {}", def); | ||||
|             return def; | ||||
|         } | ||||
|         return bucket; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -69,8 +69,8 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|             EnumSet<SchematicFeature> features | ||||
|     ) { | ||||
|         int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT); | ||||
|         boolean isRoad = features.contains(SchematicFeature.ROAD); | ||||
|         if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad && Settings.Schematics.PASTE_ON_TOP)) { | ||||
|         if ((features.contains(SchematicFeature.ROAD) && Settings.Schematics.PASTE_ROAD_ON_TOP) | ||||
|                 || (!features.contains(SchematicFeature.ROAD) && Settings.Schematics.PASTE_ON_TOP)) { | ||||
|             minY = world.SCHEM_Y; | ||||
|         } else { | ||||
|             minY = world.getMinBuildHeight(); | ||||
| @@ -341,10 +341,7 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|                 for (Entity entity : hybridPlotWorld.getPlotSchematicEntities()) { | ||||
|                     if (region.contains(entity.getLocation().toVector().toBlockPoint())) { | ||||
|                         Vector3 pos = (entity.getLocation().toVector() | ||||
|                                 .subtract(region | ||||
|                                         .getMinimumPoint() | ||||
|                                         .withY(hybridPlotWorld.getPlotSchematicMinPoint().getY()) | ||||
|                                         .toVector3())) | ||||
|                                 .subtract(region.getMinimumPoint().withY(hybridPlotWorld.getPlotSchematicMinPoint().getY()).toVector3())) | ||||
|                                 .add(min.getBlockVector3().withY(hybridPlotWorld.SCHEM_Y).toVector3()); | ||||
|                         result.setEntity(new PopulatingEntity( | ||||
|                                 entity, | ||||
| @@ -402,12 +399,6 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|         return biome == null ? hybridPlotWorld.getPlotBiome() : biome; | ||||
|     } | ||||
|  | ||||
|     private enum SchematicFeature { | ||||
|         BIOMES, | ||||
|         ROAD, | ||||
|         POPULATING | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Wrapper to allow a WorldEdit {@link Entity} to effectively have a mutable location as the location in its NBT should be changed | ||||
|      * when set to the world. | ||||
| @@ -462,4 +453,10 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private enum SchematicFeature { | ||||
|         BIOMES, | ||||
|         ROAD, | ||||
|         POPULATING | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -141,11 +141,7 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|                         (pos1.getX() + pos2.getX()) / 2, | ||||
|                         (pos1.getZ() + pos2.getZ()) / 2 | ||||
|                 ), biome)) { | ||||
|             WorldUtil.setBiome( | ||||
|                     hybridPlotWorld.getWorldName(), | ||||
|                     new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), | ||||
|                     biome | ||||
|             ); | ||||
|             WorldUtil.setBiome(hybridPlotWorld.getWorldName(), new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), biome); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -162,7 +158,6 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|         } else { | ||||
|             minY = hybridPlotWorld.getMinBuildHeight(); | ||||
|         } | ||||
|         int schemYDiff = (isRoad ? hybridPlotWorld.getRoadYStart() : hybridPlotWorld.getPlotYStart()) - minY; | ||||
|         BaseBlock airBlock = BlockTypes.AIR.getDefaultState().toBaseBlock(); | ||||
|         for (int x = pos1.getX(); x <= pos2.getX(); x++) { | ||||
|             short absX = (short) ((x - hybridPlotWorld.ROAD_OFFSET_X) % size); | ||||
| @@ -179,14 +174,10 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|                     for (int y = 0; y < blocks.length; y++) { | ||||
|                         if (blocks[y] != null) { | ||||
|                             queue.setBlock(x, minY + y, z, blocks[y]); | ||||
|                         } else if (y > schemYDiff) { | ||||
|                             // This is necessary, otherwise any blocks not specified in the schematic will remain after a clear. | ||||
|                             // This should only be done where the schematic has actually "started" | ||||
|                         } else if (!isRoad) { | ||||
|                             // This is necessary, otherwise any blocks not specified in the schematic will remain after a clear | ||||
|                             //  Do not set air for road as this may cause cavernous roads when debugroadregen is used | ||||
|                             queue.setBlock(x, minY + y, z, airBlock); | ||||
|                         } else if (isRoad) { | ||||
|                             queue.setBlock(x, minY + y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); | ||||
|                         } else { | ||||
|                             queue.setBlock(x, minY + y, z, hybridPlotWorld.MAIN_BLOCK.toPattern()); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @@ -212,18 +203,8 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|         PlotId id2 = PlotId.of(id.getX(), id.getY() + 1); | ||||
|         Location bot = getPlotBottomLocAbs(id2); | ||||
|         Location top = getPlotTopLocAbs(id); | ||||
|         Location pos1 = Location.at( | ||||
|                 hybridPlotWorld.getWorldName(), | ||||
|                 bot.getX() - 1, | ||||
|                 hybridPlotWorld.getMinGenHeight(), | ||||
|                 top.getZ() + 1 | ||||
|         ); | ||||
|         Location pos2 = Location.at( | ||||
|                 hybridPlotWorld.getWorldName(), | ||||
|                 top.getX() + 1, | ||||
|                 hybridPlotWorld.getMaxGenHeight(), | ||||
|                 bot.getZ() | ||||
|         ); | ||||
|         Location pos1 = Location.at(hybridPlotWorld.getWorldName(), bot.getX() - 1, hybridPlotWorld.getMinGenHeight(), top.getZ() + 1); | ||||
|         Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, hybridPlotWorld.getMaxGenHeight(), bot.getZ()); | ||||
|         this.resetBiome(hybridPlotWorld, pos1, pos2); | ||||
|         if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|             return true; | ||||
| @@ -293,13 +274,6 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|             queue.setCompleteTask(whenDone); | ||||
|         } | ||||
|         if (!canRegen) { | ||||
|             if (hybridPlotWorld.getMinBuildHeight() < hybridPlotWorld.getMinGenHeight()) { | ||||
|                 queue.setCuboid( | ||||
|                         pos1.withY(hybridPlotWorld.getMinBuildHeight()), | ||||
|                         pos2.withY(hybridPlotWorld.getMinGenHeight()), | ||||
|                         BlockTypes.AIR.getDefaultState() | ||||
|                 ); | ||||
|             } | ||||
|             queue.setCuboid( | ||||
|                     pos1.withY(hybridPlotWorld.getMinGenHeight()), | ||||
|                     pos2.withY(hybridPlotWorld.getMinGenHeight()), | ||||
| @@ -317,13 +291,6 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|                     pos2.withY(hybridPlotWorld.getMaxGenHeight()), | ||||
|                     BlockTypes.AIR.getDefaultState() | ||||
|             ); | ||||
|             if (hybridPlotWorld.getMaxGenHeight() < hybridPlotWorld.getMaxBuildHeight() - 1) { | ||||
|                 queue.setCuboid( | ||||
|                         pos1.withY(hybridPlotWorld.getMaxGenHeight()), | ||||
|                         pos2.withY(hybridPlotWorld.getMaxBuildHeight() - 1), | ||||
|                         BlockTypes.AIR.getDefaultState() | ||||
|                 ); | ||||
|             } | ||||
|             queue.setBiomeCuboid(pos1, pos2, biome); | ||||
|         } else { | ||||
|             queue.setRegenRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3())); | ||||
|   | ||||
| @@ -76,9 +76,6 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|      * The Y level at which schematic generation will start, lowest of either road or plot schematic generation. | ||||
|      */ | ||||
|     public int SCHEM_Y; | ||||
|  | ||||
|     private int plotY; | ||||
|     private int roadY; | ||||
|     private Location SIGN_LOCATION; | ||||
|     private File root = null; | ||||
|     private int lastOverlayHeightError = Integer.MIN_VALUE; | ||||
| @@ -255,13 +252,13 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|  | ||||
|         SCHEM_Y = schematicStartHeight(); | ||||
|  | ||||
|         // plotY and roadY are important to allow plot and/or road schematic "overflow" into each other | ||||
|         // without causing AIOOB exceptions when attempting either to set blocks to, or get block from G_SCH | ||||
|         // plotY and roadY are important to allow plot and/or road schematic "overflow" into each other without causing AIOOB | ||||
|         //  exceptions when attempting either to set blocks to, or get block from G_SCH | ||||
|         // Default plot schematic start height, normalized to the minimum height schematics are pasted from. | ||||
|         plotY = PLOT_HEIGHT - SCHEM_Y; | ||||
|         int plotY = PLOT_HEIGHT - SCHEM_Y; | ||||
|         int minRoadWall = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? Math.min(ROAD_HEIGHT, WALL_HEIGHT) : ROAD_HEIGHT; | ||||
|         // Default road schematic start height, normalized to the minimum height schematics are pasted from. | ||||
|         roadY = minRoadWall - SCHEM_Y; | ||||
|         int roadY = minRoadWall - SCHEM_Y; | ||||
|  | ||||
|         int worldGenHeight = getMaxGenHeight() - getMinGenHeight() + 1; | ||||
|  | ||||
| @@ -270,15 +267,14 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|  | ||||
|         // SCHEM_Y should be normalised to the plot "start" height | ||||
|         if (schematic3 != null) { | ||||
|             plotSchemHeight = schematic3.getClipboard().getDimensions().getY(); | ||||
|             if (plotSchemHeight == worldGenHeight) { | ||||
|             plotSchemHeight = maxSchematicHeight = schematic3.getClipboard().getDimensions().getY(); | ||||
|             if (maxSchematicHeight == worldGenHeight) { | ||||
|                 SCHEM_Y = getMinGenHeight(); | ||||
|                 plotY = 0; | ||||
|             } else if (!Settings.Schematics.PASTE_ON_TOP) { | ||||
|                 SCHEM_Y = getMinBuildHeight(); | ||||
|                 plotY = 0; | ||||
|             } | ||||
|             maxSchematicHeight = plotY + plotSchemHeight; | ||||
|         } | ||||
|  | ||||
|         int roadSchemHeight; | ||||
| @@ -327,7 +323,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|             short w3 = (short) d3.getX(); | ||||
|             short l3 = (short) d3.getZ(); | ||||
|             short h3 = (short) d3.getY(); | ||||
|             if (w3 > PLOT_WIDTH || l3 > PLOT_WIDTH) { | ||||
|             if (w3 > PLOT_WIDTH || h3 > PLOT_WIDTH) { | ||||
|                 this.ROAD_SCHEMATIC_ENABLED = true; | ||||
|             } | ||||
|             int centerShiftZ; | ||||
| @@ -382,7 +378,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         } | ||||
|         if ((schematic1 == null && schematic2 == null) || this.ROAD_WIDTH == 0) { | ||||
|             if (Settings.DEBUG) { | ||||
|                 LOGGER.info("- road schematic: false"); | ||||
|                 LOGGER.info("- schematic: false"); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| @@ -548,6 +544,14 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         return schem1PopulationNeeded || schem2PopulationNeeded || schem3PopulationNeeded; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @deprecated in favour of {@link HybridPlotWorld#getSchematicRoot()} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "6.9.0") | ||||
|     public File getRoot() { | ||||
|         return this.root; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the root folder for this world's generation schematics. May be null if schematics not initialised via | ||||
|      * {@link HybridPlotWorld#setupSchematics()} | ||||
| @@ -558,24 +562,4 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         return this.root; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the y value where the plot schematic should be pasted from. | ||||
|      * | ||||
|      * @return plot schematic y start value | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public int getPlotYStart() { | ||||
|         return SCHEM_Y + plotY; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the y value where the road schematic should be pasted from. | ||||
|      * | ||||
|      * @return road schematic y start value | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public int getRoadYStart() { | ||||
|         return SCHEM_Y + roadY; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -63,6 +63,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import java.io.File; | ||||
| import java.util.ArrayDeque; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| @@ -379,6 +380,22 @@ public class HybridUtils { | ||||
|         run.run(); | ||||
|     } | ||||
|  | ||||
|     public int checkModified(QueueCoordinator queue, int x1, int x2, int y1, int y2, int z1, int z2, BlockState[] blocks) { | ||||
|         int count = 0; | ||||
|         for (int y = y1; y <= y2; y++) { | ||||
|             for (int x = x1; x <= x2; x++) { | ||||
|                 for (int z = z1; z <= z2; z++) { | ||||
|                     BlockState block = queue.getBlock(x, y, z); | ||||
|                     boolean same = Arrays.stream(blocks).anyMatch(p -> this.worldUtil.isBlockSame(block, p)); | ||||
|                     if (!same) { | ||||
|                         count++; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return count; | ||||
|     } | ||||
|  | ||||
|     public final ArrayList<BlockVector2> getChunks(BlockVector2 region) { | ||||
|         ArrayList<BlockVector2> chunks = new ArrayList<>(); | ||||
|         int sx = region.getX() << 5; | ||||
| @@ -668,7 +685,7 @@ public class HybridUtils { | ||||
|                     } | ||||
|                     if (condition) { | ||||
|                         BaseBlock[] blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ)); | ||||
|                         int minY = plotWorld.getRoadYStart(); | ||||
|                         int minY = Settings.Schematics.PASTE_ROAD_ON_TOP ? plotWorld.SCHEM_Y : area.getMinGenHeight() + 1; | ||||
|                         int maxDy = Math.max(extend, blocks.length); | ||||
|                         for (int dy = 0; dy < maxDy; dy++) { | ||||
|                             if (dy > blocks.length - 1) { | ||||
|   | ||||
| @@ -46,7 +46,7 @@ public abstract class IndependentPlotGenerator { | ||||
|      * @param result   Queue to write to | ||||
|      * @param settings PlotArea (settings) | ||||
|      * @param biomes   If biomes should be generated | ||||
|      * @since 7.0.0 | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public abstract void generateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea settings, boolean biomes); | ||||
|  | ||||
| @@ -55,10 +55,9 @@ public abstract class IndependentPlotGenerator { | ||||
|      * | ||||
|      * @param result  Queue to write to | ||||
|      * @param setting PlotArea (settings) | ||||
|      * @since 7.0.0 | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public void populateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea setting) { | ||||
|     } | ||||
|     public void populateChunk(ZeroedDelegateScopedQueueCoordinator result, PlotArea setting) {} | ||||
|  | ||||
|     /** | ||||
|      * Return a new PlotArea object. | ||||
| @@ -104,11 +103,11 @@ public abstract class IndependentPlotGenerator { | ||||
|      * Get the biome to be generated at a specific point | ||||
|      * | ||||
|      * @param settings PlotArea settings to provide biome | ||||
|      * @param x        World x position | ||||
|      * @param y        World y position | ||||
|      * @param z        World z position | ||||
|      * @param x       World x position | ||||
|      * @param y       World y position | ||||
|      * @param z       World z position | ||||
|      * @return Biome type to be generated | ||||
|      * @since 7.0.0 | ||||
|      * @since TODO | ||||
|      */ | ||||
|     public abstract BiomeType getBiome(PlotArea settings, int x, int y, int z); | ||||
|  | ||||
|   | ||||
| @@ -185,38 +185,30 @@ public abstract class SquarePlotManager extends GridPlotManager { | ||||
|                 return null; | ||||
|             } | ||||
|             switch (hash) { | ||||
|                 case 8 -> { | ||||
|                 case 8: | ||||
|                     // north | ||||
|                     return plot.isMerged(Direction.NORTH) ? id : null; | ||||
|                 } | ||||
|                 case 4 -> { | ||||
|                 case 4: | ||||
|                     // east | ||||
|                     return plot.isMerged(Direction.EAST) ? id : null; | ||||
|                 } | ||||
|                 case 2 -> { | ||||
|                 case 2: | ||||
|                     // south | ||||
|                     return plot.isMerged(Direction.SOUTH) ? id : null; | ||||
|                 } | ||||
|                 case 1 -> { | ||||
|                 case 1: | ||||
|                     // west | ||||
|                     return plot.isMerged(Direction.WEST) ? id : null; | ||||
|                 } | ||||
|                 case 12 -> { | ||||
|                 case 12: | ||||
|                     // northeast | ||||
|                     return plot.isMerged(Direction.NORTHEAST) ? id : null; | ||||
|                 } | ||||
|                 case 6 -> { | ||||
|                 case 6: | ||||
|                     // southeast | ||||
|                     return plot.isMerged(Direction.SOUTHEAST) ? id : null; | ||||
|                 } | ||||
|                 case 3 -> { | ||||
|                 case 3: | ||||
|                     // southwest | ||||
|                     return plot.isMerged(Direction.SOUTHWEST) ? id : null; | ||||
|                 } | ||||
|                 case 9 -> { | ||||
|                 case 9: | ||||
|                     // northwest | ||||
|                     return plot.isMerged(Direction.NORTHWEST) ? id : null; | ||||
|                 } | ||||
|             } | ||||
|         } catch (Exception ignored) { | ||||
|             LOGGER.error("Invalid plot / road width in settings.yml for world: {}", squarePlotWorld.getWorldName()); | ||||
|   | ||||
| @@ -142,9 +142,7 @@ public class PlotListener { | ||||
|                     Map.Entry<UUID, List<StatusEffect>> entry = iterator.next(); | ||||
|                     List<StatusEffect> effects = entry.getValue(); | ||||
|                     effects.removeIf(effect -> currentTime > effect.expiresAt); | ||||
|                     if (effects.isEmpty()) { | ||||
|                         iterator.remove(); | ||||
|                     } | ||||
|                     if (effects.isEmpty()) iterator.remove(); | ||||
|                 } | ||||
|             } | ||||
|         }, TaskTime.seconds(1L)); | ||||
| @@ -343,14 +341,14 @@ public class PlotListener { | ||||
|             } | ||||
|  | ||||
|             TimedFlag.Timed<Integer> feed = plot.getFlag(FeedFlag.class); | ||||
|             if (feed.interval() != 0 && feed.value() != 0) { | ||||
|             if (feed.getInterval() != 0 && feed.getValue() != 0) { | ||||
|                 feedRunnable | ||||
|                         .put(player.getUUID(), new Interval(feed.interval(), feed.value(), 20)); | ||||
|                         .put(player.getUUID(), new Interval(feed.getInterval(), feed.getValue(), 20)); | ||||
|             } | ||||
|             TimedFlag.Timed<Integer> heal = plot.getFlag(HealFlag.class); | ||||
|             if (heal.interval() != 0 && heal.value() != 0) { | ||||
|             if (heal.getInterval() != 0 && heal.getValue() != 0) { | ||||
|                 healRunnable | ||||
|                         .put(player.getUUID(), new Interval(heal.interval(), heal.value(), 20)); | ||||
|                         .put(player.getUUID(), new Interval(heal.getInterval(), heal.getValue(), 20)); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
| @@ -488,9 +486,8 @@ public class PlotListener { | ||||
|  | ||||
|     /** | ||||
|      * Marks an effect as a status effect that will be removed on leaving a plot | ||||
|      * | ||||
|      * @param uuid      The uuid of the player the effect belongs to | ||||
|      * @param name      The name of the status effect | ||||
|      * @param uuid The uuid of the player the effect belongs to | ||||
|      * @param name The name of the status effect | ||||
|      * @param expiresAt The time when the effect expires | ||||
|      * @since 6.10.0 | ||||
|      */ | ||||
| @@ -521,10 +518,10 @@ public class PlotListener { | ||||
|     private record StatusEffect(@NonNull String name, long expiresAt) { | ||||
|  | ||||
|         private StatusEffect(@NonNull String name, long expiresAt) { | ||||
|             this.name = name; | ||||
|             this.expiresAt = expiresAt; | ||||
|                 this.name = name; | ||||
|                 this.expiresAt = expiresAt; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -21,11 +21,17 @@ package com.plotsquared.core.location; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.StringMan; | ||||
|  | ||||
| public record ChunkWrapper( | ||||
|         String world, | ||||
|         int x, | ||||
|         int z | ||||
| ) { | ||||
| public class ChunkWrapper { | ||||
|  | ||||
|     public final int x; | ||||
|     public final int z; | ||||
|     public final String world; | ||||
|  | ||||
|     public ChunkWrapper(String world, int x, int z) { | ||||
|         this.world = world; | ||||
|         this.x = x; | ||||
|         this.z = z; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int hashCode() { | ||||
|   | ||||
| @@ -51,6 +51,7 @@ public final class UncheckedWorldLocation extends Location { | ||||
|      * @param y     Y coordinate | ||||
|      * @param z     Z coordinate | ||||
|      * @return New location | ||||
|      * | ||||
|      * @since 6.9.0 | ||||
|      */ | ||||
|     @DoNotUse | ||||
|   | ||||
| @@ -288,7 +288,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer, | ||||
|      * | ||||
|      * @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea} | ||||
|      */ | ||||
|     public Plot getCurrentPlot() { | ||||
|     public @Nullable Plot getCurrentPlot() { | ||||
|         try (final MetaDataAccess<Plot> lastPlotAccess = | ||||
|                      this.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { | ||||
|             if (lastPlotAccess.get().orElse(null) == null && !Settings.Enabled_Components.EVENTS) { | ||||
|   | ||||
| @@ -215,11 +215,17 @@ public final class BlockBucket implements ConfigurationSerializable { | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     private record Range( | ||||
|             int min, | ||||
|             int max, | ||||
|             boolean automatic | ||||
|     ) { | ||||
|     private static final class Range { | ||||
|  | ||||
|         private final int min; | ||||
|         private final int max; | ||||
|         private final boolean automatic; | ||||
|  | ||||
|         public Range(int min, int max, boolean automatic) { | ||||
|             this.min = min; | ||||
|             this.max = max; | ||||
|             this.automatic = automatic; | ||||
|         } | ||||
|  | ||||
|         public int getWeight() { | ||||
|             return max - min; | ||||
| @@ -229,6 +235,46 @@ public final class BlockBucket implements ConfigurationSerializable { | ||||
|             return num <= max && num >= min; | ||||
|         } | ||||
|  | ||||
|         public int getMin() { | ||||
|             return this.min; | ||||
|         } | ||||
|  | ||||
|         public int getMax() { | ||||
|             return this.max; | ||||
|         } | ||||
|  | ||||
|         public boolean equals(final Object o) { | ||||
|             if (o == this) { | ||||
|                 return true; | ||||
|             } | ||||
|             if (!(o instanceof final Range other)) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (this.getMin() != other.getMin()) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (this.getMax() != other.getMax()) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (this.isAutomatic() != other.isAutomatic()) { | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         public int hashCode() { | ||||
|             final int PRIME = 59; | ||||
|             int result = 1; | ||||
|             result = result * PRIME + this.getMin(); | ||||
|             result = result * PRIME + this.getMax(); | ||||
|             result = result * PRIME + (this.isAutomatic() ? 79 : 97); | ||||
|             return result; | ||||
|         } | ||||
|  | ||||
|         public boolean isAutomatic() { | ||||
|             return this.automatic; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -20,6 +20,7 @@ package com.plotsquared.core.plot; | ||||
|  | ||||
| import com.google.common.collect.ImmutableSet; | ||||
| import com.google.common.collect.Lists; | ||||
| import com.google.common.collect.Sets; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.command.Like; | ||||
| @@ -2417,6 +2418,7 @@ public class Plot { | ||||
|         if (!this.isMerged()) { | ||||
|             Location pos1 = this.getBottomAbs().withY(getArea().getMinBuildHeight()); | ||||
|             Location pos2 = this.getTopAbs().withY(getArea().getMaxBuildHeight()); | ||||
|             this.connectedCache = Sets.newHashSet(this); | ||||
|             CuboidRegion rg = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()); | ||||
|             return Collections.singleton(rg); | ||||
|         } | ||||
|   | ||||
| @@ -657,11 +657,9 @@ public abstract class PlotArea implements ComponentLike { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("height.height_limit"), | ||||
|                     TagResolver.builder() | ||||
|                             .tag("minheight", Tag.inserting(Component.text(minBuildHeight))) | ||||
|                             .tag( | ||||
|                                     "maxheight", | ||||
|                                     Tag.inserting(Component.text(maxBuildHeight)) | ||||
|                             ).build() | ||||
|                             .tag("minHeight", Tag.inserting(Component.text(minBuildHeight))) | ||||
|                             .tag("maxHeight", | ||||
|                             Tag.inserting(Component.text(maxBuildHeight))).build() | ||||
|             ); | ||||
|             // Return true if "failed" as the method will always be inverted otherwise | ||||
|             return true; | ||||
| @@ -1019,7 +1017,7 @@ public abstract class PlotArea implements ComponentLike { | ||||
|      * | ||||
|      * @param plotIds     List of plot IDs to merge | ||||
|      * @param removeRoads If the roads between plots should be removed | ||||
|      * @param whenDone    Task to run when any merge world changes are complete. Also runs if no changes were made. Does not | ||||
|      * @param whenDone  Task to run when any merge world changes are complete. Also runs if no changes were made. Does not | ||||
|      *                    run if there was an error or if too few plots IDs were supplied. | ||||
|      * @return if merges were completed successfully. | ||||
|      * @since 6.9.0 | ||||
|   | ||||
| @@ -100,7 +100,7 @@ public class PlotInventory { | ||||
|      * Put an item into this inventory | ||||
|      * | ||||
|      * @param index the index (= slot) where to place the item | ||||
|      * @param item  the item to place | ||||
|      * @param item the item to place | ||||
|      * @see #setItemChecked(int, PlotItemStack) | ||||
|      */ | ||||
|     public void setItem(int index, PlotItemStack item) { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user