├── .gitattributes ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .editorconfig ├── settings.gradle.kts ├── gradle.properties ├── .gitignore ├── LICENSE.md ├── patches ├── server │ ├── 0039-Improve-validation-of-ResourceLocations.patch │ ├── 0032-Patch-invalid-entity-rotation-log-spam.patch │ ├── 0028-Refuse-to-convert-legacy-messages-over-1k-characters.patch │ ├── 0040-Don-t-log-on-too-many-chained-updates.patch │ ├── 0047-Add-length-limit-to-note-block-sound.patch │ ├── 0020-Don-t-log-invalid-teams-to-console.patch │ ├── 0017-Fix-negative-death-times.patch │ ├── 0033-Limit-sculk-catalyst-cursor-positions.patch │ ├── 0037-Don-t-warn-on-duplicate-entity-UUIDs.patch │ ├── 0008-Validate-BlockState-and-SoundEvent-values.patch │ ├── 0006-ItemEntity-Check-if-items-are-air-before-calling-set.patch │ ├── 0021-Fixes-out-of-bounds-HangingEntity-crash-exploit.patch │ ├── 0036-Prevent-player-banning-using-duplicate-UUIDs.patch │ ├── 0038-Limit-beacon-effectRange.patch │ ├── 0005-Ignore-errors-thrown-when-trying-to-remove-minecart-.patch │ ├── 0013-Prevent-attributes-with-invalid-namespaces-from-bein.patch │ ├── 0024-Add-spectator-teleport-event.patch │ ├── 0009-Do-not-log-invalid-items-in-HoverEvent-and-ItemFrame.patch │ ├── 0010-Reject-oversized-components-from-updating.patch │ ├── 0002-UUID-validation.patch │ ├── 0003-Fixes-log-spam-caused-by-invalid-entities-in-beehive.patch │ ├── 0025-Prevent-invalid-container-events.patch │ ├── 0045-Mute-invalid-attributes.patch │ ├── 0027-Validate-block-entity-entity-tag-query-positions.patch │ ├── 0016-Fixes-creative-killing-potion-effects-and-certain-po.patch │ ├── 0014-Don-t-query-player-data-in-the-nbt-component.patch │ ├── 0035-Limit-map-decorations.patch │ ├── 0046-Mute-invalid-Enderdragon-phases.patch │ ├── 0043-Limit-save-data-for-Bees-and-Vexes.patch │ ├── 0007-Fixes-Knowledge-Books-causing-log-spam-when-invalid-.patch │ ├── 0026-Disable-running-commands-in-books-by-default.patch │ ├── 0029-Fix-ClickEvents-on-Signs-bypassing-permissions.patch │ ├── 0041-Fix-packet-related-lag-exploits.patch │ ├── 0050-Add-depth-limit-to-updateCustomBlockEntityTag.patch │ ├── 0044-Add-depth-limit-to-SNBT.patch │ ├── 0030-Prevent-velocity-freeze.patch │ ├── 0031-Patch-large-selector-distance-crash.patch │ ├── 0042-Implement-command-block-events.patch │ ├── 0048-Change-version-fetcher-to-AMG.patch │ ├── 0049-Add-depth-limit-to-Component-deserialization.patch │ ├── 0018-Limit-amount-of-vehicle-collision-checks-to-3-and-di.patch │ ├── 0019-Add-custom-classes-used-by-Scissors.patch │ ├── 0034-Add-configuration-option-to-disable-chat-signatures.patch │ ├── 0004-ResourceLocation-validation.patch │ ├── 0001-Build-changes.patch │ ├── 0015-Limit-string-tag-visitors-to-1024-elements.patch │ ├── 0022-Add-MasterBlockFireEvent.patch │ ├── 0012-Better-handling-of-invalid-JSON-components.patch │ └── 0023-Reset-large-tags.patch └── api │ ├── 0003-Add-Scissors-configuration-file.patch │ ├── 0001-Add-MasterBlockFireEvent.patch │ ├── 0002-Add-spectator-teleport-event.patch │ └── 0004-Add-command-block-player-edit-event.patch ├── .github └── workflows │ └── build.yml ├── licenses └── MIT.md ├── README.md ├── Jenkinsfile ├── gradlew.bat └── gradlew /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.sh text eol=lf 4 | gradlew text eol=lf 5 | *.bat text eol=crlf 6 | 7 | *.jar binary 8 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AtlasMediaGroup/Scissors/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.java] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=true 5 | indent_style=space 6 | indent_size=4 7 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven("https://repo.papermc.io/repository/maven-public/") 5 | } 6 | } 7 | 8 | rootProject.name = "Scissors" 9 | 10 | include("Scissors-API", "Scissors-Server") 11 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | group=me.totalfreedom.scissors 2 | version=1.20.4-R0.1-SNAPSHOT 3 | 4 | mcVersion=1.20.4 5 | paperRef=ba31f4128208e954d6648001724887352f71ece9 6 | 7 | org.gradle.caching=true 8 | org.gradle.parallel=true 9 | org.gradle.vfs.watch=false 10 | org.gradle.jvmargs=-Xmx4096m 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | build/ 3 | 4 | # Eclipse stuff 5 | .classpath 6 | .project 7 | .settings/ 8 | 9 | # VSCode stuff 10 | .vscode/ 11 | 12 | # netbeans 13 | nbproject/ 14 | nbactions.xml 15 | 16 | # we use maven! 17 | build.xml 18 | 19 | # maven 20 | target/ 21 | dependency-reduced-pom.xml 22 | 23 | # vim 24 | .*.sw[a-p] 25 | 26 | # various other potential build files 27 | build/ 28 | bin/ 29 | dist/ 30 | manifest.mf 31 | 32 | # Mac filesystem dust 33 | .DS_Store/ 34 | .DS_Store 35 | 36 | # intellij 37 | *.iml 38 | *.ipr 39 | *.iws 40 | .idea/ 41 | out/ 42 | 43 | # Linux temp files 44 | *~ 45 | 46 | # other stuff 47 | run/ 48 | 49 | Scissors-Server 50 | Scissors-API 51 | 52 | !gradle/wrapper/gradle-wrapper.jar 53 | 54 | paper-api-generator 55 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Scissors inherits its licensing from upstream projects. 2 | 3 | As such, Scissors is licensed under the 4 | [GNU General Public License version 3](licenses/GPL.md); as it inherits it from Paper and Spigot, 5 | who in turn inherits it from the original Bukkit and Craftbukkit projects. 6 | 7 | Any author who is _not_ listed below should be presumed to have released their work 8 | under the original [GPL](licenses/GPL.md) license. 9 | 10 | In the interest of promoting a better Minecraft platform for everyone, contributors 11 | may choose to release their code under the more permissive [MIT License](licenses/MIT.md). 12 | 13 | The authors listed below have chosen to release their code under that more permissive 14 | [MIT License](licenses/MIT.md). Any contributor who wants their name added below 15 | should submit a pull request to this project to add their name. 16 | 17 | ```text 18 | Allink (allinkdev) 19 | Luna (LunaWasFlaggedAgain) 20 | Telesphoreo 21 | ``` 22 | -------------------------------------------------------------------------------- /patches/server/0039-Improve-validation-of-ResourceLocations.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Tue, 13 Jun 2023 18:29:18 -0300 4 | Subject: [PATCH] Improve validation of ResourceLocations 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java 8 | index 5014192edb9616ce725fc1592832034789527b6f..64da1b0afd51720803aba0d9e86d0b1743bdb0da 100644 9 | --- a/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java 10 | +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftNamespacedKey.java 11 | @@ -21,6 +21,7 @@ public final class CraftNamespacedKey { 12 | } 13 | 14 | public static NamespacedKey fromMinecraft(ResourceLocation minecraft) { 15 | + if (minecraft == null) throw new IllegalArgumentException("Null ResourceLocation provided"); // Scissors 16 | return new NamespacedKey(minecraft.getNamespace(), minecraft.getPath()); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /patches/api/0003-Add-Scissors-configuration-file.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Sun, 10 Jul 2022 10:12:04 +0100 4 | Subject: [PATCH] Add Scissors configuration file 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java 8 | index 4ff1b38eb65f97344257204cf018f176f247ed36..be766fc9c24bedcc58dac2cb1991345bf5ed17e0 100644 9 | --- a/src/main/java/org/bukkit/Server.java 10 | +++ b/src/main/java/org/bukkit/Server.java 11 | @@ -2235,6 +2235,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi 12 | } 13 | // Paper end 14 | 15 | + // Scissors start 16 | + @NotNull 17 | + public org.bukkit.configuration.file.YamlConfiguration getScissorsConfig() { 18 | + throw new UnsupportedOperationException("Not supported yet."); 19 | + } 20 | + // Scissors end 21 | + 22 | /** 23 | * Sends the component to the player 24 | * 25 | -------------------------------------------------------------------------------- /patches/server/0032-Patch-invalid-entity-rotation-log-spam.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Mon, 20 Mar 2023 07:04:50 +0000 4 | Subject: [PATCH] Patch invalid entity rotation log spam 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java 8 | index 2ecf2d8ff546ed097cb3b547db22d28a31d29ec4..36b1a1cc66b9852d3b10c09cbf39262f51996663 100644 9 | --- a/src/main/java/net/minecraft/world/entity/Entity.java 10 | +++ b/src/main/java/net/minecraft/world/entity/Entity.java 11 | @@ -4751,7 +4751,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S 12 | 13 | public void setXRot(float pitch) { 14 | if (!Float.isFinite(pitch)) { 15 | - Util.logAndPauseIfInIde("Invalid entity rotation: " + pitch + ", discarding."); 16 | + // Scissors - Patch invalid entity rotation log spam 17 | } else { 18 | this.xRot = pitch; 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Patch and Build 2 | 3 | on: 4 | push: 5 | branches: [ "**" ] 6 | pull_request: 7 | 8 | jobs: 9 | build: 10 | # Only run on PRs if the source branch is on someone else's repo 11 | if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout Git Repository 15 | uses: actions/checkout@v3 16 | - name: Validate Gradle wrapper 17 | uses: gradle/wrapper-validation-action@v1 18 | - name: Setup Gradle 19 | uses: gradle/gradle-build-action@v2 20 | - name: Set up JDK 21 | uses: actions/setup-java@v3 22 | with: 23 | distribution: 'temurin' 24 | java-version: '17' 25 | - name: Configure Git User Details 26 | run: git config --global user.email "actions@github.com" && git config --global user.name "Github Actions" 27 | - name: Apply Patches 28 | run: ./gradlew applyPatches 29 | - name: Build 30 | run: ./gradlew build 31 | -------------------------------------------------------------------------------- /patches/server/0028-Refuse-to-convert-legacy-messages-over-1k-characters.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Tue, 16 Aug 2022 17:13:02 +0100 4 | Subject: [PATCH] Refuse to convert legacy messages over 1k characters 5 | 6 | 7 | diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java 8 | index 753200057e74b8e2d5274894b982e6ee946a559e..25df28c8a2061a754cb576634b63d5ca6e5011d1 100644 9 | --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java 10 | +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java 11 | @@ -198,6 +198,7 @@ public final class CraftChatMessage { 12 | } 13 | 14 | public static Component[] fromString(String message, boolean keepNewlines, boolean plain) { 15 | + if (message.length() > 1_000) return new Component[]{Component.empty()}; // Scissors - Refuse to convert legacy messages over 1k characters 16 | return new StringMessage(message, keepNewlines, plain).getOutput(); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /licenses/MIT.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation 6 | files (the “Software”), to deal in the Software without 7 | restriction, including without limitation the rights to use, 8 | copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /patches/server/0040-Don-t-log-on-too-many-chained-updates.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Sat, 1 Jul 2023 21:22:29 -0300 4 | Subject: [PATCH] Don't log on too many chained updates 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java 8 | index 106af2b2c7ff72c7549975aef75cdcff8d9a7d97..ecdcf4cf8650270ce7595905ce9d498eee520dcd 100644 9 | --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java 10 | +++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java 11 | @@ -58,7 +58,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { 12 | this.stack.push(entry); 13 | } 14 | } else if (this.count - 1 == this.maxChainedNeighborUpdates) { 15 | - LOGGER.error("Too many chained neighbor updates. Skipping the rest. First skipped position: " + pos.toShortString()); 16 | + // Scissors - don't log 17 | } 18 | 19 | if (!bl) { 20 | -------------------------------------------------------------------------------- /patches/server/0047-Add-length-limit-to-note-block-sound.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Fri, 25 Aug 2023 11:51:47 +0100 4 | Subject: [PATCH] Add length limit to note block sound 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java 8 | index 6f52256bfb668aee7fd1628c1c0c7b3434b847a6..74f1227ecf664cf0d4f62d6f9c3e65ffc07b146e 100644 9 | --- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java 10 | +++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java 11 | @@ -113,7 +113,7 @@ public class SkullBlockEntity extends BlockEntity { 12 | } 13 | 14 | if (nbt.contains("note_block_sound", 8)) { 15 | - this.noteBlockSound = ResourceLocation.tryParse(nbt.getString("note_block_sound")); 16 | + this.noteBlockSound = ResourceLocation.tryParse(StringUtil.truncateStringIfNecessary(nbt.getString("note_block_sound"), 32767, false)); // Scissors - Add length limit to note block sound 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /patches/server/0020-Don-t-log-invalid-teams-to-console.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Tue, 17 May 2022 05:57:52 +0100 4 | Subject: [PATCH] Don't log invalid teams to console 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java 8 | index 60961c54e870148b5c649045e7347ca1064b6bde..0ce25857188029335d0afd0a9f0c22b79d4b0b69 100644 9 | --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java 10 | +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java 11 | @@ -869,7 +869,7 @@ public abstract class LivingEntity extends Entity implements Attackable { 12 | boolean flag = scoreboardteam != null && this.level().getScoreboard().addPlayerToTeam(this.getStringUUID(), scoreboardteam); 13 | 14 | if (!flag) { 15 | - LivingEntity.LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", s); 16 | + // Scissors - Prevent log spam possible with this error message, easily provokable by players in creative. 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /patches/server/0017-Fix-negative-death-times.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Sat, 24 Feb 2024 15:32:48 -0600 4 | Subject: [PATCH] Fix negative death times 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java 8 | index e9bb7feb591032904516d1b9374f486d8a7d066c..60961c54e870148b5c649045e7347ca1064b6bde 100644 9 | --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java 10 | +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java 11 | @@ -629,7 +629,7 @@ public abstract class LivingEntity extends Entity implements Attackable { 12 | 13 | protected void tickDeath() { 14 | ++this.deathTime; 15 | - if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) { 16 | + if ((this.deathTime >= 20 || this.deathTime <= 0) && !this.level().isClientSide() && !this.isRemoved()) { // Scissors 17 | this.level().broadcastEntityEvent(this, (byte) 60); 18 | this.remove(Entity.RemovalReason.KILLED, EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause 19 | } 20 | -------------------------------------------------------------------------------- /patches/server/0033-Limit-sculk-catalyst-cursor-positions.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Mon, 10 Apr 2023 13:56:18 -0300 4 | Subject: [PATCH] Limit sculk catalyst cursor positions 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/block/SculkSpreader.java b/src/main/java/net/minecraft/world/level/block/SculkSpreader.java 8 | index 01e13e6d3ebd84cff0019f56efff16747420dc95..d4058bc31ca291cbc95eeef594fc35e1ff6a3dde 100644 9 | --- a/src/main/java/net/minecraft/world/level/block/SculkSpreader.java 10 | +++ b/src/main/java/net/minecraft/world/level/block/SculkSpreader.java 11 | @@ -181,7 +181,7 @@ public class SculkSpreader { 12 | 13 | while (iterator.hasNext()) { 14 | SculkSpreader.ChargeCursor sculkspreader_a = (SculkSpreader.ChargeCursor) iterator.next(); 15 | - 16 | + if (!world.getMinecraftWorld().isLoadedAndInBounds(sculkspreader_a.getPos())) continue; // Scissors 17 | sculkspreader_a.update(world, pos, random, this, shouldConvertToBlock); 18 | if (sculkspreader_a.charge <= 0) { 19 | world.levelEvent(3006, sculkspreader_a.getPos(), 0); 20 | -------------------------------------------------------------------------------- /patches/server/0037-Don-t-warn-on-duplicate-entity-UUIDs.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Fri, 28 Apr 2023 16:46:00 -0300 4 | Subject: [PATCH] Don't warn on duplicate entity UUIDs 5 | 6 | 7 | diff --git a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java 8 | index 15ee41452992714108efe53b708b5a4e1da7c1ff..5054dce35127cb0132431021578c345fcbb1f92a 100644 9 | --- a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java 10 | +++ b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java 11 | @@ -415,7 +415,7 @@ public final class EntityLookup implements LevelEntityGetter { 12 | return false; 13 | } 14 | if (this.entityByUUID.containsKey(entity.getUUID())) { 15 | - LOGGER.warn("Entity uuid already exists: " + entity.getUUID() + ", mapped to " + this.entityByUUID.get(entity.getUUID()) + ", can't add " + entity); 16 | + // Scissors - Don't warn on duplicate entity UUIDs 17 | return false; 18 | } 19 | this.entityById.put(entity.getId(), entity); 20 | -------------------------------------------------------------------------------- /patches/server/0008-Validate-BlockState-and-SoundEvent-values.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Sun, 13 Mar 2022 21:56:29 -0600 4 | Subject: [PATCH] Validate BlockState and SoundEvent values 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/nbt/NbtUtils.java b/src/main/java/net/minecraft/nbt/NbtUtils.java 8 | index fe4bea6af0d8734f3a5b972dce5f1e3914d6690e..0ee64be4288f59240beec26c470b78cc1aeac424 100644 9 | --- a/src/main/java/net/minecraft/nbt/NbtUtils.java 10 | +++ b/src/main/java/net/minecraft/nbt/NbtUtils.java 11 | @@ -223,7 +223,7 @@ public final class NbtUtils { 12 | return Blocks.AIR.defaultBlockState(); 13 | } else { 14 | // Paper start - Validate resource location 15 | - ResourceLocation resourceLocation = ResourceLocation.tryParse(nbt.getString("Name")); 16 | + ResourceLocation resourceLocation = ResourceLocation.tryParse(nbt.getString("Name")); // Scissors - Validate BlockState 17 | Optional> optional = resourceLocation != null ? blockLookup.get(ResourceKey.create(Registries.BLOCK, resourceLocation)) : Optional.empty(); 18 | // Paper end - Validate resource location 19 | if (optional.isEmpty()) { 20 | -------------------------------------------------------------------------------- /patches/server/0006-ItemEntity-Check-if-items-are-air-before-calling-set.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Sun, 13 Mar 2022 14:38:38 -0300 4 | Subject: [PATCH] ItemEntity - Check if items are air before calling setItem 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java 8 | index c7f06c3cfb737bd17a706798bf9cf0e1af5f0cc0..4fd00227d035284688e641cb2c55a3214dcbaa38 100644 9 | --- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java 10 | +++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java 11 | @@ -445,11 +445,15 @@ public class ItemEntity extends Entity implements TraceableEntity { 12 | 13 | CompoundTag nbttagcompound1 = nbt.getCompound("Item"); 14 | 15 | - this.setItem(ItemStack.of(nbttagcompound1)); 16 | - if (this.getItem().isEmpty()) { 17 | - this.discard(null); // CraftBukkit - add Bukkit remove cause 18 | + // Scissors start 19 | + ItemStack item = ItemStack.of(nbttagcompound1); 20 | + if (item.isEmpty()) { 21 | + this.discard(null); 22 | + return; 23 | } 24 | 25 | + this.setItem(item); 26 | + // Scissors end 27 | } 28 | 29 | @Override 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Scissors [![Build Status](https://ci.scissors.gg/job/Scissors/job/1.20.4/badge/icon)](https://ci.scissors.gg/job/Scissors/job/1.20.4/) 2 | 3 | Scissors is a fork of Paper that aims to fix exploits possible in Creative Mode. Many of these exploits are ones that 4 | Paper's own team has either refused to fix or would have. 5 | 6 | ## Links 7 | ### [Scissors Download](https://ci.plex.us.org/job/Scissors) 8 | ### [Scissors Javadoc](https://javadoc.scissors.gg/1.20.4) 9 | ### [Scissors Announcements](https://totalfreedom.tf/forums/scissors-announcements.55) 10 | ### [Scissors General Discussion](https://totalfreedom.tf/forums/scissors-discussion.56/) 11 | 12 | ## Tasks 13 | ``` 14 | Paperweight tasks 15 | ----------------- 16 | applyApiPatches 17 | applyPatches 18 | applyServerPatches 19 | cleanCache - Delete the project setup cache and task outputs. 20 | createMojmapBundlerJar - Build a runnable bundler jar 21 | createMojmapPaperclipJar - Build a runnable paperclip jar 22 | createReobfBundlerJar - Build a runnable bundler jar 23 | createReobfPaperclipJar - Build a runnable paperclip jar 24 | generateDevelopmentBundle 25 | rebuildApiPatches 26 | rebuildPatches 27 | rebuildServerPatches 28 | reobfJar - Re-obfuscate the built jar to obf mappings 29 | runDev - Spin up a non-relocated Mojang-mapped test server 30 | runReobf - Spin up a test server from the reobfJar output jar 31 | runShadow - Spin up a test server from the shadowJar archiveFile 32 | ``` 33 | -------------------------------------------------------------------------------- /patches/server/0021-Fixes-out-of-bounds-HangingEntity-crash-exploit.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Fri, 19 Aug 2022 00:49:38 -0600 4 | Subject: [PATCH] Fixes out of bounds HangingEntity crash exploit 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java 8 | index eaad15a4d201356c34c1a09c7fbe5c35f76a2176..e166411e05287d97ea7c9d35b19d4ae3106401c3 100644 9 | --- a/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java 10 | +++ b/src/main/java/net/minecraft/world/entity/decoration/HangingEntity.java 11 | @@ -280,6 +280,13 @@ public abstract class HangingEntity extends Entity { 12 | public void readAdditionalSaveData(CompoundTag nbt) { 13 | BlockPos blockposition = new BlockPos(nbt.getInt("TileX"), nbt.getInt("TileY"), nbt.getInt("TileZ")); 14 | 15 | + // Scissors start - Fixes exploit where bad TileX, TileY, and TileZ coordinates can crash servers 16 | + if (level().isLoadedAndInBounds(blockposition)) 17 | + { 18 | + this.pos = blockposition; 19 | + } 20 | + // Scissors end 21 | + 22 | if (!blockposition.closerThan(this.blockPosition(), 16.0D)) { 23 | HangingEntity.LOGGER.error("Hanging entity at invalid position: {}", blockposition); 24 | } else { 25 | -------------------------------------------------------------------------------- /patches/server/0036-Prevent-player-banning-using-duplicate-UUIDs.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Fri, 28 Apr 2023 16:44:50 -0300 4 | Subject: [PATCH] Prevent player banning using duplicate UUIDs 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java 8 | index 502bdc726b7890b00ee36871d905dea44e8719e3..1fbc8b372271bb4cd4375ca6b6b1d7e7961094fb 100644 9 | --- a/src/main/java/net/minecraft/server/level/ServerLevel.java 10 | +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java 11 | @@ -1667,7 +1667,13 @@ public class ServerLevel extends Level implements WorldGenLevel { 12 | if (entity != null) { 13 | ServerLevel.LOGGER.warn("Force-added player with duplicate UUID {}", player.getUUID()); 14 | entity.unRide(); 15 | - this.removePlayerImmediately((ServerPlayer) entity, Entity.RemovalReason.DISCARDED); 16 | + // Scissors start - Prevent player banning using duplicate UUIDs 17 | + if (entity instanceof ServerPlayer serverPlayer) { 18 | + this.removePlayerImmediately(serverPlayer, Entity.RemovalReason.DISCARDED); 19 | + } else { 20 | + entity.discard(null); 21 | + } 22 | + // Scissors end 23 | } 24 | 25 | this.entityLookup.addNewEntity(player); // Paper - rewite chunk system 26 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | environment { 4 | GITHUB_BRANCH = "${BRANCH_NAME}" 5 | } 6 | stages { 7 | stage('applyPatches') { 8 | steps { 9 | withGradle { 10 | sh './gradlew applyPatches --no-daemon --refresh-dependencies' 11 | } 12 | } 13 | } 14 | stage('paperclipJar') { 15 | steps { 16 | withGradle { 17 | sh './gradlew createReobfPaperclipJar --no-daemon --refresh-dependencies' 18 | } 19 | sh """ 20 | #!/bin/sh 21 | BRANCH=\$(echo "\${BRANCH_NAME}" | sed 's/\\//_/g') 22 | mv \${WORKSPACE}/build/libs/Scissors-paperclip-*.jar \${WORKSPACE}/build/libs/scissors-\${BRANCH}-\${BUILD_NUMBER}.jar 23 | rm \${WORKSPACE}/build/libs/Scissors-bundler-*.jar 24 | """ 25 | } 26 | } 27 | stage('test') { 28 | steps { 29 | withGradle { 30 | sh './gradlew test --no-daemon' 31 | } 32 | } 33 | } 34 | } 35 | post { 36 | always { 37 | archiveArtifacts artifacts: 'build/libs/scissors-*.jar', fingerprint: true 38 | junit 'Scissors-Server/build/test-results/test/*.xml' 39 | junit 'Scissors-API/build/test-results/test/*.xml' 40 | cleanWs() 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /patches/server/0038-Limit-beacon-effectRange.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Wed, 7 Jun 2023 16:50:35 -0300 4 | Subject: [PATCH] Limit beacon effectRange 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java 8 | index 4b81b0180dfc96fc6a88646838a886ca5b5d301b..63ea77b3e965ff18571492d511ef7c1082441f9d 100644 9 | --- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java 10 | +++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java 11 | @@ -87,7 +87,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name 12 | private double effectRange = -1; 13 | 14 | public double getEffectRange() { 15 | - if (this.effectRange < 0) { 16 | + if (this.effectRange < 0 || this.effectRange > 256) { // Scissors 17 | return this.levels * 10 + 10; 18 | } else { 19 | return effectRange; 20 | @@ -456,6 +456,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name 21 | 22 | this.lockKey = LockCode.fromTag(nbt); 23 | this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper - Custom beacon ranges 24 | + if (this.effectRange > 256) this.effectRange = 256; // Scissors 25 | } 26 | 27 | @Override 28 | -------------------------------------------------------------------------------- /patches/server/0005-Ignore-errors-thrown-when-trying-to-remove-minecart-.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Sun, 13 Mar 2022 08:14:44 -0600 4 | Subject: [PATCH] Ignore errors thrown when trying to remove minecart entities 5 | with content in them 6 | 7 | 8 | diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java 9 | index 756d0434472921992c9d84597d7c9c824e93614c..77e9e106c522712a484d01bf7e7434c380de3621 100644 10 | --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java 11 | +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java 12 | @@ -147,7 +147,11 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme 13 | public void remove(Entity.RemovalReason entity_removalreason, EntityRemoveEvent.Cause cause) { 14 | // CraftBukkit end 15 | if (!this.level().isClientSide && entity_removalreason.shouldDestroy()) { 16 | - Containers.dropContents(this.level(), (Entity) this, (Container) this); 17 | + // Scissors start - Ignore errors thrown when trying to remove minecart entities with content in them 18 | + try { 19 | + Containers.dropContents(this.level(), (Entity) this, (Container) this); 20 | + } catch (Exception ignored) {} 21 | + // Scissors end 22 | } 23 | 24 | super.remove(entity_removalreason, cause); // CraftBukkit - add Bukkit remove cause 25 | -------------------------------------------------------------------------------- /patches/server/0013-Prevent-attributes-with-invalid-namespaces-from-bein.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Wed, 30 Mar 2022 18:20:09 -0600 4 | Subject: [PATCH] Prevent attributes with invalid namespaces from being applied 5 | to CraftMetaItems 6 | 7 | 8 | diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java 9 | index 5cd0fbac267f9c69c5de4c200a95860f5c56d42e..f2ccf2af05524be91eb0f4855cb8006dea2aede4 100644 10 | --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java 11 | +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java 12 | @@ -47,6 +47,7 @@ import net.minecraft.nbt.NbtIo; 13 | import net.minecraft.nbt.StringTag; 14 | import net.minecraft.nbt.Tag; 15 | import net.minecraft.network.chat.Component; 16 | +import net.minecraft.resources.ResourceLocation; // Scissors 17 | import net.minecraft.world.item.BlockItem; 18 | import net.minecraft.world.level.block.state.BlockState; 19 | import org.apache.commons.lang3.EnumUtils; 20 | @@ -488,7 +489,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { 21 | AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); 22 | 23 | String attributeName = org.bukkit.craftbukkit.attribute.CraftAttributeMap.convertIfNeeded(entry.getString(CraftMetaItem.ATTRIBUTES_IDENTIFIER.NBT)); // Paper 24 | - if (attributeName == null || attributeName.isEmpty()) { 25 | + if (attributeName == null || attributeName.isEmpty() || attributeName.length() > 256 || !ResourceLocation.isValidResourceLocation(attributeName)) { // Scissors 26 | continue; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /patches/server/0024-Add-spectator-teleport-event.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Tue, 5 Jul 2022 04:12:31 +0100 4 | Subject: [PATCH] Add spectator teleport event 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 8 | index fe2ef36ab5dc4b933abf24dbfd0e811c53239cf0..f14e5f5867b0319c1f3f25ac607ac5e2b0992991 100644 9 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 10 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 11 | @@ -1,5 +1,6 @@ 12 | package net.minecraft.server.network; 13 | 14 | +import me.totalfreedom.scissors.event.player.SpectatorTeleportEvent; // Scissors 15 | import com.google.common.collect.Lists; 16 | import com.google.common.primitives.Floats; 17 | import com.mojang.authlib.GameProfile; 18 | @@ -2033,6 +2034,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 19 | Entity entity = packet.getEntity(worldserver); 20 | 21 | if (entity != null) { 22 | + // Scissors start - Add spectator teleport event 23 | + final SpectatorTeleportEvent event = new SpectatorTeleportEvent(this.player.getBukkitEntity(), entity.getBukkitEntity()); 24 | + if (!event.callEvent()) { 25 | + return; 26 | + } 27 | + // Scissors end 28 | this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit 29 | return; 30 | } 31 | -------------------------------------------------------------------------------- /patches/server/0009-Do-not-log-invalid-items-in-HoverEvent-and-ItemFrame.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Mon, 15 Apr 2024 22:26:14 -0500 4 | Subject: [PATCH] Do not log invalid items in HoverEvent and ItemFrame 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/chat/HoverEvent.java b/src/main/java/net/minecraft/network/chat/HoverEvent.java 8 | index 433e586bed53a8c17adec74b3088899c748d4be3..a82b4e39c3160114aded3f33c85fad2e95065b72 100644 9 | --- a/src/main/java/net/minecraft/network/chat/HoverEvent.java 10 | +++ b/src/main/java/net/minecraft/network/chat/HoverEvent.java 11 | @@ -261,7 +261,7 @@ public class HoverEvent { 12 | CompoundTag compoundTag = TagParser.parseTag(text.getString()); 13 | return DataResult.success(new HoverEvent.ItemStackInfo(ItemStack.of(compoundTag))); 14 | } catch (CommandSyntaxException var2) { 15 | - return DataResult.error(() -> "Failed to parse item tag: " + var2.getMessage()); 16 | + return null; 17 | } 18 | } 19 | } 20 | diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java 21 | index c34701f95580e4cf45fe086115563127432a28c5..fc7547381a5dd7c0aae352c0cae72a980953b98f 100644 22 | --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java 23 | +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java 24 | @@ -436,7 +436,7 @@ public class ItemFrame extends HangingEntity { 25 | ItemStack itemstack = ItemStack.of(nbttagcompound1); 26 | 27 | if (itemstack.isEmpty()) { 28 | - ItemFrame.LOGGER.warn("Unable to load item from: {}", nbttagcompound1); 29 | + // Scissors - ignore invalid items 30 | } 31 | 32 | ItemStack itemstack1 = this.getItem(); 33 | -------------------------------------------------------------------------------- /patches/server/0010-Reject-oversized-components-from-updating.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Mon, 28 Mar 2022 16:49:17 -0600 4 | Subject: [PATCH] Reject oversized components from updating 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/chat/ComponentUtils.java b/src/main/java/net/minecraft/network/chat/ComponentUtils.java 8 | index 3365aed2b67ae0e4dd0410f5190ba474f146139b..43b62a07b040b1d7d76dc8f940f35b51d1d5f868 100644 9 | --- a/src/main/java/net/minecraft/network/chat/ComponentUtils.java 10 | +++ b/src/main/java/net/minecraft/network/chat/ComponentUtils.java 11 | @@ -38,8 +38,9 @@ public class ComponentUtils { 12 | } 13 | 14 | public static MutableComponent updateForEntity(@Nullable CommandSourceStack source, Component text, @Nullable Entity sender, int depth) throws CommandSyntaxException { 15 | + MutableComponent result; // Scissors 16 | if (depth > 100) { 17 | - return text.copy(); 18 | + result = text.copy(); // Scissors 19 | } else { 20 | // Paper start - adventure; pass actual vanilla component 21 | if (text instanceof io.papermc.paper.adventure.AdventureComponent adventureComponent) { 22 | @@ -52,8 +53,9 @@ public class ComponentUtils { 23 | mutableComponent.append(updateForEntity(source, component, sender, depth + 1)); 24 | } 25 | 26 | - return mutableComponent.withStyle(resolveStyle(source, text.getStyle(), sender, depth)); 27 | + result = mutableComponent.withStyle(resolveStyle(source, text.getStyle(), sender, depth)); // Scissors 28 | } 29 | + return Component.Serializer.toJson(result).length() > 65535 ? Component.empty() : result; // Scissors 30 | } 31 | 32 | private static Style resolveStyle(@Nullable CommandSourceStack source, Style style, @Nullable Entity sender, int depth) throws CommandSyntaxException { 33 | -------------------------------------------------------------------------------- /patches/server/0002-UUID-validation.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Sun, 10 Dec 2023 13:11:22 -0600 4 | Subject: [PATCH] UUID validation 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/chat/HoverEvent.java b/src/main/java/net/minecraft/network/chat/HoverEvent.java 8 | index 9067bab8ec695417d479393f07d9bc6432427d73..433e586bed53a8c17adec74b3088899c748d4be3 100644 9 | --- a/src/main/java/net/minecraft/network/chat/HoverEvent.java 10 | +++ b/src/main/java/net/minecraft/network/chat/HoverEvent.java 11 | @@ -20,6 +20,7 @@ import net.minecraft.nbt.CompoundTag; 12 | import net.minecraft.nbt.TagParser; 13 | import net.minecraft.resources.ResourceLocation; 14 | import net.minecraft.util.ExtraCodecs; 15 | +import net.minecraft.util.GsonHelper; 16 | import net.minecraft.util.StringRepresentable; 17 | import net.minecraft.world.entity.EntityType; 18 | import net.minecraft.world.item.Item; 19 | @@ -148,7 +149,14 @@ public class HoverEvent { 20 | CompoundTag compoundTag = TagParser.parseTag(text.getString()); 21 | Component component = Component.Serializer.fromJson(compoundTag.getString("name")); 22 | EntityType entityType = BuiltInRegistries.ENTITY_TYPE.get(new ResourceLocation(compoundTag.getString("type"))); 23 | - UUID uUID = UUID.fromString(compoundTag.getString("id")); 24 | + // Scissors start 25 | + UUID uUID; 26 | + try { 27 | + uUID = UUID.fromString(compoundTag.getString("id")); 28 | + } catch (Exception ex) { 29 | + return null; 30 | + } 31 | + // Scissors end 32 | return DataResult.success(new HoverEvent.EntityTooltipInfo(entityType, uUID, component)); 33 | } catch (Exception var5) { 34 | return DataResult.error(() -> "Failed to parse tooltip: " + var5.getMessage()); 35 | -------------------------------------------------------------------------------- /patches/api/0001-Add-MasterBlockFireEvent.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Mon, 4 Jul 2022 16:44:35 +0100 4 | Subject: [PATCH] Add MasterBlockFireEvent 5 | 6 | 7 | diff --git a/src/main/java/me/totalfreedom/scissors/event/block/MasterBlockFireEvent.java b/src/main/java/me/totalfreedom/scissors/event/block/MasterBlockFireEvent.java 8 | new file mode 100644 9 | index 0000000000000000000000000000000000000000..812e6ae9f1c8eb9558e5109c522d3ce3a7deb35c 10 | --- /dev/null 11 | +++ b/src/main/java/me/totalfreedom/scissors/event/block/MasterBlockFireEvent.java 12 | @@ -0,0 +1,51 @@ 13 | +package me.totalfreedom.scissors.event.block; 14 | + 15 | +import org.bukkit.Location; 16 | +import org.bukkit.event.Cancellable; 17 | +import org.bukkit.event.Event; 18 | +import org.bukkit.event.HandlerList; 19 | +import org.jetbrains.annotations.NotNull; 20 | + 21 | +/** 22 | + * Called when a GameMasterBlock is fired (i.e. command block, structure block, jigsaw block) 23 | + */ 24 | +public class MasterBlockFireEvent extends Event implements Cancellable 25 | +{ 26 | + 27 | + private static final HandlerList handlers = new HandlerList(); 28 | + private boolean cancelled; 29 | + private final Location at; 30 | + 31 | + public MasterBlockFireEvent(@NotNull Location at) 32 | + { 33 | + this.at = at; 34 | + } 35 | + 36 | + public static @NotNull HandlerList getHandlerList() 37 | + { 38 | + return handlers; 39 | + } 40 | + 41 | + public @NotNull Location getAt() 42 | + { 43 | + return this.at; 44 | + } 45 | + 46 | + @Override 47 | + public @NotNull HandlerList getHandlers() 48 | + { 49 | + return handlers; 50 | + } 51 | + 52 | + @Override 53 | + public boolean isCancelled() 54 | + { 55 | + return cancelled; 56 | + } 57 | + 58 | + @Override 59 | + public void setCancelled(boolean cancelled) 60 | + { 61 | + this.cancelled = cancelled; 62 | + } 63 | +} 64 | -------------------------------------------------------------------------------- /patches/server/0003-Fixes-log-spam-caused-by-invalid-entities-in-beehive.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Sun, 10 Dec 2023 16:57:48 -0600 4 | Subject: [PATCH] Fixes log spam caused by invalid entities in beehives 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java 8 | index d445ed0895293dd45c36226051f5809be8587ebe..b9c8b70fb0bf47ffe62cf0d082156479d07da331 100644 9 | --- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java 10 | +++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java 11 | @@ -11,6 +11,7 @@ import net.minecraft.nbt.CompoundTag; 12 | import net.minecraft.nbt.ListTag; 13 | import net.minecraft.nbt.NbtUtils; 14 | import net.minecraft.network.protocol.game.DebugPackets; 15 | +import net.minecraft.resources.ResourceLocation; 16 | import net.minecraft.sounds.SoundEvents; 17 | import net.minecraft.sounds.SoundSource; 18 | import net.minecraft.tags.BlockTags; 19 | @@ -380,6 +381,13 @@ public class BeehiveBlockEntity extends BlockEntity { 20 | 21 | for (int i = 0; i < nbttaglist.size(); ++i) { 22 | CompoundTag nbttagcompound1 = nbttaglist.getCompound(i); 23 | + 24 | + // Scissors start - Do not allow invalid entities from being used for bees 25 | + if (!nbttagcompound1.contains("id") || !ResourceLocation.isValidResourceLocation(nbttagcompound1.getString("id")) || EntityType.byString(nbttagcompound1.getString("id")).isEmpty()) { 26 | + continue; 27 | + } 28 | + // Scissors end 29 | + 30 | BeehiveBlockEntity.BeeData tileentitybeehive_hivebee = new BeehiveBlockEntity.BeeData(nbttagcompound1.getCompound("EntityData").copy(), nbttagcompound1.getInt("TicksInHive"), nbttagcompound1.getInt("MinOccupationTicks")); 31 | 32 | this.stored.add(tileentitybeehive_hivebee); 33 | -------------------------------------------------------------------------------- /patches/server/0025-Prevent-invalid-container-events.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Sun, 10 Jul 2022 02:55:01 +0100 4 | Subject: [PATCH] Prevent invalid container events 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 8 | index f14e5f5867b0319c1f3f25ac607ac5e2b0992991..4582ef637075e64c0b6ff234d3c0cd30ba074b38 100644 9 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 10 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 11 | @@ -29,6 +29,7 @@ import java.util.function.UnaryOperator; 12 | import java.util.stream.Collectors; 13 | import java.util.stream.Stream; 14 | import javax.annotation.Nullable; 15 | +import net.kyori.adventure.text.format.NamedTextColor; // Scissors 16 | import net.minecraft.ChatFormatting; 17 | import net.minecraft.SharedConstants; 18 | import net.minecraft.Util; 19 | @@ -2898,6 +2899,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 20 | return; 21 | } 22 | 23 | + // Scissors start - Do not call events when the slot/button number is invalid 24 | + final int sentSlotNum = packet.getSlotNum(); 25 | + if((Mth.clamp(sentSlotNum, -1, this.player.containerMenu.slots.size() - 1) != sentSlotNum) && sentSlotNum != -999) 26 | + { 27 | + this.getCraftPlayer().kick( 28 | + net.kyori.adventure.text.Component.text("Invalid container click slot (Hacking?)") 29 | + .color(NamedTextColor.RED) 30 | + ); 31 | + return; 32 | + } 33 | + // Scissors end 34 | + 35 | InventoryView inventory = this.player.containerMenu.getBukkitView(); 36 | SlotType type = inventory.getSlotType(packet.getSlotNum()); 37 | 38 | -------------------------------------------------------------------------------- /patches/server/0045-Mute-invalid-attributes.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Thu, 6 Jul 2023 23:01:12 +0100 4 | Subject: [PATCH] Mute invalid attributes 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java 8 | index b99a080ab27e24d8131fda931ca70d6d271bb01c..f88b31d9bfc8b332230fa318ba2c1de14d5cc9be 100644 9 | --- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java 10 | +++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java 11 | @@ -135,7 +135,10 @@ public class AttributeMap { 12 | if (attributeInstance != null) { 13 | attributeInstance.load(compoundTag); 14 | } 15 | - }, () -> LOGGER.warn("Ignoring unknown attribute '{}'", string)); 16 | + 17 | + }, () -> { 18 | + // LOGGER.warn("Ignoring unknown attribute '{}'", (Object)string); // Scissors - Mute invalid attributes 19 | + }); 20 | } 21 | } 22 | 23 | diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeModifier.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeModifier.java 24 | index a38e91552ead256bd8dd3b74794d742555681c2d..116af10e6e2467a3e3b0095c4968a79ebb4a19d6 100644 25 | --- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeModifier.java 26 | +++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeModifier.java 27 | @@ -90,7 +90,7 @@ public class AttributeModifier { 28 | AttributeModifier.Operation operation = AttributeModifier.Operation.fromValue(nbt.getInt("Operation")); 29 | return new AttributeModifier(uUID, nbt.getString("Name"), nbt.getDouble("Amount"), operation); 30 | } catch (Exception var3) { 31 | - LOGGER.warn("Unable to create attribute: {}", var3.getMessage()); 32 | + // LOGGER.warn("Unable to create attribute: {}", var3.getMessage()); // Scissors - Mute invalid attributes 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /patches/api/0002-Add-spectator-teleport-event.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Tue, 5 Jul 2022 04:10:29 +0100 4 | Subject: [PATCH] Add spectator teleport event 5 | 6 | 7 | diff --git a/src/main/java/me/totalfreedom/scissors/event/player/SpectatorTeleportEvent.java b/src/main/java/me/totalfreedom/scissors/event/player/SpectatorTeleportEvent.java 8 | new file mode 100644 9 | index 0000000000000000000000000000000000000000..e4c9256c78f8b395aea86e9ea1a112f8e7426c1f 10 | --- /dev/null 11 | +++ b/src/main/java/me/totalfreedom/scissors/event/player/SpectatorTeleportEvent.java 12 | @@ -0,0 +1,60 @@ 13 | +package me.totalfreedom.scissors.event.player; 14 | + 15 | +import org.bukkit.entity.Entity; 16 | +import org.bukkit.entity.Player; 17 | +import org.bukkit.event.Cancellable; 18 | +import org.bukkit.event.Event; 19 | +import org.bukkit.event.HandlerList; 20 | +import org.jetbrains.annotations.NotNull; 21 | + 22 | +/** 23 | + * Called whenever a spectator attempts to teleport to an entity 24 | + */ 25 | +public class SpectatorTeleportEvent extends Event implements Cancellable 26 | +{ 27 | + private static final HandlerList handlerList = new HandlerList(); 28 | + private final Player player; 29 | + private final Entity target; 30 | + private boolean cancelled; 31 | + 32 | + public SpectatorTeleportEvent(@NotNull Player player, @NotNull Entity target) 33 | + { 34 | + this.player = player; 35 | + this.target = target; 36 | + } 37 | + 38 | + @NotNull 39 | + public Player getPlayer() { 40 | + return this.player; 41 | + } 42 | + 43 | + @NotNull 44 | + public Entity getTarget() { 45 | + return this.target; 46 | + } 47 | + 48 | + @Override 49 | + public boolean isCancelled() 50 | + { 51 | + return cancelled; 52 | + } 53 | + 54 | + @Override 55 | + public void setCancelled(boolean cancelled) 56 | + { 57 | + this.cancelled = cancelled; 58 | + } 59 | + 60 | + @NotNull 61 | + @Override 62 | + public HandlerList getHandlers() 63 | + { 64 | + return handlerList; 65 | + } 66 | + 67 | + @NotNull 68 | + public static org.bukkit.event.HandlerList getHandlerList() 69 | + { 70 | + return handlerList; 71 | + } 72 | +} 73 | -------------------------------------------------------------------------------- /patches/server/0027-Validate-block-entity-entity-tag-query-positions.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Mon, 11 Jul 2022 17:29:12 -0300 4 | Subject: [PATCH] Validate block entity/entity tag query positions 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 8 | index 4582ef637075e64c0b6ff234d3c0cd30ba074b38..80f0f88258770862f419e4faba4cfca4c0457b2c 100644 9 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 10 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 11 | @@ -1278,7 +1278,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 12 | if (this.player.hasPermissions(2)) { 13 | Entity entity = this.player.level().getEntity(packet.getEntityId()); 14 | 15 | - if (entity != null) { 16 | + if (entity != null && this.player.distanceToSqr(entity.position().x, entity.position().y, entity.position().z) < 32 * 32) { // Scissors - Validate entity tag query positions 17 | CompoundTag nbttagcompound = entity.saveWithoutId(new CompoundTag()); 18 | 19 | this.player.connection.send(new ClientboundTagQueryPacket(packet.getTransactionId(), nbttagcompound)); 20 | @@ -1310,7 +1310,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 21 | @Override 22 | public void handleBlockEntityTagQuery(ServerboundBlockEntityTagQuery packet) { 23 | PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); 24 | - if (this.player.hasPermissions(2)) { 25 | + // Scissors start - Validate block entity tag query positions 26 | + if (this.player.hasPermissions(2) && this.player.level().isLoadedAndInBounds(packet.getPos()) 27 | + && this.player.distanceToSqr(packet.getPos().getX(), packet.getPos().getY(), packet.getPos().getZ()) < 32 * 32) { 28 | + // Scissors end 29 | BlockEntity tileentity = this.player.level().getBlockEntity(packet.getPos()); 30 | CompoundTag nbttagcompound = tileentity != null ? tileentity.saveWithoutMetadata() : null; 31 | 32 | -------------------------------------------------------------------------------- /patches/server/0016-Fixes-creative-killing-potion-effects-and-certain-po.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Mon, 11 Apr 2022 13:33:52 -0600 4 | Subject: [PATCH] Fixes creative-killing potion effects and certain potion 5 | effect overflows 6 | 7 | 8 | diff --git a/src/main/java/net/minecraft/world/effect/HealOrHarmMobEffect.java b/src/main/java/net/minecraft/world/effect/HealOrHarmMobEffect.java 9 | index 1c7794de5f0a7238b944c9473e2cc9d011ef2306..9c594c504611b9da5fcd119284b2dcb4b59d3bf4 100644 10 | --- a/src/main/java/net/minecraft/world/effect/HealOrHarmMobEffect.java 11 | +++ b/src/main/java/net/minecraft/world/effect/HealOrHarmMobEffect.java 12 | @@ -16,6 +16,11 @@ class HealOrHarmMobEffect extends InstantenousMobEffect { 13 | @Override 14 | public void applyEffectTick(LivingEntity entity, int amplifier) { 15 | super.applyEffectTick(entity, amplifier); 16 | + // Scissors start - Don't apply any healing/harming effects for Creative/Invulnerable players and cap the amplifier for those who aren't. 17 | + if (entity instanceof net.minecraft.world.entity.player.Player player && (player.isCreative() || player.isInvulnerable())) return; 18 | + amplifier = Math.min(Math.abs(amplifier), 124); 19 | + // Scissors end 20 | + 21 | if (this.isHarm == entity.isInvertedHealAndHarm()) { 22 | entity.heal((float) Math.max(4 << amplifier, 0), org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.MAGIC); // CraftBukkit 23 | } else { 24 | @@ -27,6 +32,10 @@ class HealOrHarmMobEffect extends InstantenousMobEffect { 25 | @Override 26 | public void applyInstantenousEffect(@Nullable Entity source, @Nullable Entity attacker, LivingEntity target, int amplifier, double proximity) { 27 | int j; 28 | + // Scissors start - Don't apply any healing/harming effects for Creative/Invulnerable players and cap the amplifier for those who aren't. 29 | + if (target instanceof net.minecraft.world.entity.player.Player player && (player.isCreative() || player.isInvulnerable())) return; 30 | + amplifier = Math.min(Math.abs(amplifier), 124); 31 | + // Scissors end 32 | 33 | if (this.isHarm == target.isInvertedHealAndHarm()) { 34 | j = (int) (proximity * (double) (4 << amplifier) + 0.5D); 35 | -------------------------------------------------------------------------------- /patches/server/0014-Don-t-query-player-data-in-the-nbt-component.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Sun, 10 Dec 2023 17:39:52 -0600 4 | Subject: [PATCH] Don't query player data in the `nbt` component 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/chat/contents/EntityDataSource.java b/src/main/java/net/minecraft/network/chat/contents/EntityDataSource.java 8 | index 2750702cff35762bc817ffbe5bf81631e86bc49b..8714c3be77490a87aa6df0ff36a87557c6b99e25 100644 9 | --- a/src/main/java/net/minecraft/network/chat/contents/EntityDataSource.java 10 | +++ b/src/main/java/net/minecraft/network/chat/contents/EntityDataSource.java 11 | @@ -8,12 +8,15 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; 12 | import java.util.List; 13 | import java.util.stream.Stream; 14 | import javax.annotation.Nullable; 15 | + 16 | +import me.totalfreedom.scissors.ScissorsConfig; 17 | import net.minecraft.advancements.critereon.NbtPredicate; 18 | import net.minecraft.commands.CommandSourceStack; 19 | import net.minecraft.commands.arguments.selector.EntitySelector; 20 | import net.minecraft.commands.arguments.selector.EntitySelectorParser; 21 | import net.minecraft.nbt.CompoundTag; 22 | import net.minecraft.world.entity.Entity; 23 | +import net.minecraft.world.entity.player.Player; 24 | 25 | public record EntityDataSource(String selectorPattern, @Nullable EntitySelector compiledSelector) implements DataSource { 26 | public static final MapCodec SUB_CODEC = RecordCodecBuilder.mapCodec( 27 | @@ -39,7 +42,11 @@ public record EntityDataSource(String selectorPattern, @Nullable EntitySelector 28 | public Stream getData(CommandSourceStack source) throws CommandSyntaxException { 29 | if (this.compiledSelector != null) { 30 | List list = this.compiledSelector.findEntities(source); 31 | - return list.stream().map(NbtPredicate::getEntityTagToCompare); 32 | + // Scissors start 33 | + Stream stream = list.stream(); 34 | + if (ScissorsConfig.excludePlayersFromNbtComponents) stream = stream.filter((entity) -> !(entity instanceof Player)); 35 | + return stream.map(NbtPredicate::getEntityTagToCompare); 36 | + // Scissors end 37 | } else { 38 | return Stream.empty(); 39 | } 40 | -------------------------------------------------------------------------------- /patches/server/0035-Limit-map-decorations.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Fri, 28 Apr 2023 16:29:23 -0300 4 | Subject: [PATCH] Limit map decorations 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundMapItemDataPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundMapItemDataPacket.java 8 | index 02e3d1c9c18952ba53507f7b6887fd3c81af33a9..61573844b236838fd219526ea35df8c7b0c94026 100644 9 | --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundMapItemDataPacket.java 10 | +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundMapItemDataPacket.java 11 | @@ -63,7 +63,8 @@ public class ClientboundMapItemDataPacket implements Packet 32) { 31 | + return; 32 | + } 33 | + // Scissors end 34 | int i = 1 << this.scale; 35 | float f = (float) (x - (double) this.centerX) / (float) i; 36 | float f1 = (float) (z - (double) this.centerZ) / (float) i; 37 | -------------------------------------------------------------------------------- /patches/server/0046-Mute-invalid-Enderdragon-phases.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Thu, 6 Jul 2023 23:34:46 +0100 4 | Subject: [PATCH] Mute invalid Enderdragon phases 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonChargePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonChargePlayerPhase.java 8 | index 1b1a210a86121049e507a497649727a99452c0a2..a8bcadbf64d5034b172427e16b1468b4c91c4518 100644 9 | --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonChargePlayerPhase.java 10 | +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonChargePlayerPhase.java 11 | @@ -20,7 +20,7 @@ public class DragonChargePlayerPhase extends AbstractDragonPhaseInstance { 12 | @Override 13 | public void doServerTick() { 14 | if (this.targetLocation == null) { 15 | - LOGGER.warn("Aborting charge player as no target was set."); 16 | + // LOGGER.warn("Aborting charge player as no target was set."); // Scissors - Mute invalid Enderdragon phases 17 | this.dragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); 18 | } else if (this.timeSinceCharge > 0 && this.timeSinceCharge++ >= 10) { 19 | this.dragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); 20 | diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java 21 | index c5269c3117901b8521720d1b32689d7f600f20a3..3a8839ee4cb8cafb927ad49a9e8f9a2955eef973 100644 22 | --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java 23 | +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonStrafePlayerPhase.java 24 | @@ -31,7 +31,7 @@ public class DragonStrafePlayerPhase extends AbstractDragonPhaseInstance { 25 | @Override 26 | public void doServerTick() { 27 | if (this.attackTarget == null) { 28 | - LOGGER.warn("Skipping player strafe phase because no player was found"); 29 | + // LOGGER.warn("Skipping player strafe phase because no player was found"); // Scissors - Mute invalid Enderdragon phases 30 | this.dragon.getPhaseManager().setPhase(EnderDragonPhase.HOLDING_PATTERN); 31 | } else { 32 | if (this.currentPath != null && this.currentPath.isDone()) { 33 | -------------------------------------------------------------------------------- /patches/server/0043-Limit-save-data-for-Bees-and-Vexes.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Wed, 5 Jul 2023 22:58:24 +0100 4 | Subject: [PATCH] Limit save data for Bees and Vexes 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java 8 | index f9521a6e115f0c975a7885b024c99eae300b63bf..c1598d0caee40a7d73af549b31b61ee7aae77315 100644 9 | --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java 10 | +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java 11 | @@ -234,8 +234,12 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { 12 | @Override 13 | public void readAdditionalSaveData(CompoundTag nbt) { 14 | this.hivePos = null; 15 | - if (nbt.contains("HivePos")) { 16 | - this.hivePos = NbtUtils.readBlockPos(nbt.getCompound("HivePos")); 17 | + if (nbt.contains("HivePos")) 18 | + { 19 | + // Scissors start - Limit HivePos 20 | + final BlockPos savedHivePos = NbtUtils.readBlockPos(nbt.getCompound("HivePos")); 21 | + this.hivePos = this.level().isLoadedAndInBounds(savedHivePos) ? savedHivePos : null; 22 | + // Scissors end - Limit HivePos 23 | } 24 | 25 | this.savedFlowerPos = null; 26 | diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java 27 | index f443006c1e32feee97b32312814e2447a50c45e2..ad418449f5ffd4bcceb5834b1385dc69259f3a21 100644 28 | --- a/src/main/java/net/minecraft/world/entity/monster/Vex.java 29 | +++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java 30 | @@ -118,8 +118,12 @@ public class Vex extends Monster implements TraceableEntity { 31 | @Override 32 | public void readAdditionalSaveData(CompoundTag nbt) { 33 | super.readAdditionalSaveData(nbt); 34 | - if (nbt.contains("BoundX")) { 35 | - this.boundOrigin = new BlockPos(nbt.getInt("BoundX"), nbt.getInt("BoundY"), nbt.getInt("BoundZ")); 36 | + if (nbt.contains("BoundX")) 37 | + { 38 | + // Scissors start - Limit Vex bound origin 39 | + final BlockPos savedBoundOrigin = new BlockPos(nbt.getInt("BoundX"), nbt.getInt("BoundY"), nbt.getInt("BoundZ")); 40 | + this.boundOrigin = this.level().isLoadedAndInBounds(savedBoundOrigin) ? savedBoundOrigin : null; 41 | + // Scissors end - Limit Vex bound origin 42 | } 43 | 44 | if (nbt.contains("LifeTicks")) { 45 | -------------------------------------------------------------------------------- /patches/server/0007-Fixes-Knowledge-Books-causing-log-spam-when-invalid-.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Sun, 13 Mar 2022 18:42:07 -0600 4 | Subject: [PATCH] Fixes Knowledge Books causing log spam when invalid data is 5 | provided 6 | 7 | 8 | diff --git a/src/main/java/net/minecraft/world/item/KnowledgeBookItem.java b/src/main/java/net/minecraft/world/item/KnowledgeBookItem.java 9 | index 5ebc309aed545a4c22970e617519fe916a29fa3c..14a35465e41c9ecb51bea5b084e2637ebd21d295 100644 10 | --- a/src/main/java/net/minecraft/world/item/KnowledgeBookItem.java 11 | +++ b/src/main/java/net/minecraft/world/item/KnowledgeBookItem.java 12 | @@ -40,9 +40,9 @@ public class KnowledgeBookItem extends Item { 13 | 14 | for (int i = 0; i < listTag.size(); i++) { 15 | String string = listTag.getString(i); 16 | - Optional> optional = recipeManager.byKey(new ResourceLocation(string)); 17 | + Optional> optional = recipeManager.byKey(ResourceLocation.tryParse(string)); // Scissors - Validate resource locations 18 | if (!optional.isPresent()) { 19 | - LOGGER.error("Invalid recipe: {}", string); 20 | + // Scissors - Don't log errors caused by invalid recipes being provided 21 | return InteractionResultHolder.fail(itemStack); 22 | } 23 | 24 | @@ -55,7 +55,7 @@ public class KnowledgeBookItem extends Item { 25 | 26 | return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide()); 27 | } else { 28 | - LOGGER.error("Tag not valid: {}", compoundTag); 29 | + // Scissors - Don't throw errors into the logs if an NBT compound isn't present or is missing the Recipes tag. 30 | return InteractionResultHolder.fail(itemStack); 31 | } 32 | } 33 | diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java 34 | index e904bf8b6a7d18a0e846c3b59e2d7f3d6e530e39..65b076b376bf6ab363a3eb62dfa2c96c45624957 100644 35 | --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java 36 | +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaKnowledgeBook.java 37 | @@ -41,7 +41,11 @@ public class CraftMetaKnowledgeBook extends CraftMetaItem implements KnowledgeBo 38 | for (int i = 0; i < pages.size(); i++) { 39 | String recipe = pages.getString(i); 40 | 41 | - this.addRecipe(CraftNamespacedKey.fromString(recipe)); 42 | + // Scissors start - Don't add recipes with invalid namespaces 43 | + try { 44 | + this.addRecipe(CraftNamespacedKey.fromString(recipe)); 45 | + } catch (Exception ignored) {} 46 | + // Scissors end 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /patches/server/0026-Disable-running-commands-in-books-by-default.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Sun, 10 Jul 2022 10:29:03 +0100 4 | Subject: [PATCH] Disable running commands in books by default 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/item/WrittenBookItem.java b/src/main/java/net/minecraft/world/item/WrittenBookItem.java 8 | index 793ab8acd7445984cff2628e3f001661dc20c8e5..0e6e0d6a9c645db0121637262a6cf90172d3c385 100644 9 | --- a/src/main/java/net/minecraft/world/item/WrittenBookItem.java 10 | +++ b/src/main/java/net/minecraft/world/item/WrittenBookItem.java 11 | @@ -2,6 +2,7 @@ package net.minecraft.world.item; 12 | 13 | import java.util.List; 14 | import javax.annotation.Nullable; 15 | +import me.totalfreedom.scissors.ScissorsConfig; // Scissors 16 | import net.minecraft.ChatFormatting; 17 | import net.minecraft.commands.CommandSourceStack; 18 | import net.minecraft.core.BlockPos; 19 | @@ -9,8 +10,7 @@ import net.minecraft.nbt.CompoundTag; 20 | import net.minecraft.nbt.ListTag; 21 | import net.minecraft.nbt.StringTag; 22 | import net.minecraft.nbt.Tag; 23 | -import net.minecraft.network.chat.Component; 24 | -import net.minecraft.network.chat.ComponentUtils; 25 | +import net.minecraft.network.chat.*; // Scissors 26 | import net.minecraft.stats.Stats; 27 | import net.minecraft.util.StringUtil; 28 | import net.minecraft.world.InteractionHand; 29 | @@ -162,9 +162,43 @@ public class WrittenBookItem extends Item { 30 | component2 = Component.literal(text); 31 | } 32 | 33 | - return Component.Serializer.toJson(component2); 34 | + return Component.Serializer.toJson(!ScissorsConfig.runCommandsInBooks ? sanitize(component2, 0) : component2); // Scissors - Allow server owners to disable run command in books 35 | } 36 | 37 | + // Scissors start - Allow server owners to disable run command in books 38 | + public static Component sanitize(Component component, int depth) 39 | + { 40 | + if (depth > 128) 41 | + { 42 | + return Component.nullToEmpty("Sanitization function depth limit exceeded"); 43 | + } 44 | + 45 | + MutableComponent component2 = component.copy(); 46 | + 47 | + final Style style = component2.getStyle(); 48 | + final ClickEvent clickEvent = style.getClickEvent(); 49 | + 50 | + if (clickEvent != null && clickEvent.getAction().equals(ClickEvent.Action.RUN_COMMAND)) 51 | + { 52 | + final String clickEventValue = clickEvent.getValue(); 53 | + 54 | + component2 = component2.copy().setStyle(style 55 | + .withClickEvent(null) 56 | + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.nullToEmpty("Would've " + (clickEventValue.startsWith("/") ? "ran" : "said") + ": " + clickEvent.getValue()))) 57 | + ); 58 | + } 59 | + 60 | + final List processedExtra = component2.getSiblings() 61 | + .stream() 62 | + .map(comp -> sanitize(comp, depth + 1)) 63 | + .toList(); 64 | + component2.getSiblings().clear(); 65 | + component2.getSiblings().addAll(processedExtra); 66 | + 67 | + return component2; 68 | + } 69 | + // Scissors end 70 | + 71 | @Override 72 | public boolean isFoil(ItemStack stack) { 73 | return true; 74 | -------------------------------------------------------------------------------- /patches/server/0029-Fix-ClickEvents-on-Signs-bypassing-permissions.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Tue, 23 Jan 2024 19:04:22 -0600 4 | Subject: [PATCH] Fix ClickEvents on Signs bypassing permissions 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java 8 | index 927c7ea03560be0c86884cec70ee8e408e66cb07..c4bb1739ddcfd473ef788f97afa1019e24da8561 100644 9 | --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java 10 | +++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java 11 | @@ -8,8 +8,10 @@ import java.util.Objects; 12 | import java.util.UUID; 13 | import java.util.function.UnaryOperator; 14 | import javax.annotation.Nullable; 15 | +import me.totalfreedom.scissors.ScissorsConfig; 16 | import net.minecraft.commands.CommandSource; 17 | import net.minecraft.commands.CommandSourceStack; 18 | +import net.minecraft.commands.Commands; 19 | import net.minecraft.core.BlockPos; 20 | import net.minecraft.nbt.CompoundTag; 21 | import net.minecraft.nbt.NbtOps; 22 | @@ -19,6 +21,7 @@ import net.minecraft.network.chat.Component; 23 | import net.minecraft.network.chat.ComponentUtils; 24 | import net.minecraft.network.chat.Style; 25 | import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; 26 | +import net.minecraft.server.MinecraftServer; 27 | import net.minecraft.server.level.ServerLevel; 28 | import net.minecraft.server.level.ServerPlayer; 29 | import net.minecraft.server.network.FilteredText; 30 | @@ -32,6 +35,8 @@ import net.minecraft.world.level.block.SignBlock; 31 | import net.minecraft.world.level.block.state.BlockState; 32 | import net.minecraft.world.phys.Vec2; 33 | import net.minecraft.world.phys.Vec3; 34 | +import org.bukkit.craftbukkit.CraftServer; 35 | +import org.bukkit.craftbukkit.entity.CraftHumanEntity; 36 | import org.slf4j.Logger; 37 | import org.bukkit.block.sign.Side; 38 | import org.bukkit.craftbukkit.block.CraftBlock; 39 | @@ -289,6 +294,21 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C 40 | } 41 | player.getServer().getCommands().performPrefixedCommand(this.createCommandSourceStack(((org.bukkit.craftbukkit.entity.CraftPlayer) event.getPlayer()).getHandle(), world, pos), event.getMessage()); 42 | // Paper end - Fix commands from signs not firing command events 43 | + // Scissors start - Add optional permissions to command signs 44 | + final MinecraftServer vanillaServer = player.getServer(); 45 | + final CraftServer craftServer = vanillaServer.server; 46 | + final CraftHumanEntity craftPlayer = player.getBukkitEntity(); 47 | + final Commands commands = vanillaServer.getCommands(); 48 | + 49 | + if (ScissorsConfig.commandSignsBypassPermissions) 50 | + { 51 | + commands.performPrefixedCommand(this.createCommandSourceStack(((org.bukkit.craftbukkit.entity.CraftPlayer) event.getPlayer()).getHandle(), world, pos), event.getMessage()); 52 | + } 53 | + else 54 | + { 55 | + craftServer.dispatchCommand(craftPlayer, command.substring(1)); 56 | + } 57 | + // Scissors end 58 | flag1 = true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /patches/server/0041-Fix-packet-related-lag-exploits.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Tue, 4 Jul 2023 18:49:34 -0300 4 | Subject: [PATCH] Fix packet-related lag exploits 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 8 | index c0aa9520d547d6d77169fd1dbb02844b90ef4a1d..843793437737305bbdec598326a813f84b820d12 100644 9 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 10 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 11 | @@ -865,7 +865,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 12 | this.player.sendSystemMessage(Component.translatable("advMode.notEnabled")); 13 | } else if (!this.player.canUseGameMasterBlocks() && (!this.player.isCreative() || !this.player.getBukkitEntity().hasPermission("minecraft.commandblock"))) { // Paper - command block permission 14 | this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); 15 | - } else { 16 | + } else if (this.player.level().isLoadedAndInBounds(packet.getPos())) { // Scissors 17 | BaseCommandBlock commandblocklistenerabstract = null; 18 | CommandBlockEntity tileentitycommand = null; 19 | BlockPos blockposition = packet.getPos(); 20 | @@ -1013,7 +1013,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 21 | @Override 22 | public void handleSetStructureBlock(ServerboundSetStructureBlockPacket packet) { 23 | PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); 24 | - if (this.player.canUseGameMasterBlocks()) { 25 | + if (this.player.canUseGameMasterBlocks() && this.player.level().isLoadedAndInBounds(packet.getPos())) { // Scissors 26 | BlockPos blockposition = packet.getPos(); 27 | BlockState iblockdata = this.player.level().getBlockState(blockposition); 28 | BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); 29 | @@ -1071,7 +1071,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 30 | @Override 31 | public void handleSetJigsawBlock(ServerboundSetJigsawBlockPacket packet) { 32 | PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); 33 | - if (this.player.canUseGameMasterBlocks()) { 34 | + if (this.player.canUseGameMasterBlocks() && this.player.level().isLoadedAndInBounds(packet.getPos())) { // Scissors 35 | BlockPos blockposition = packet.getPos(); 36 | BlockState iblockdata = this.player.level().getBlockState(blockposition); 37 | BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); 38 | @@ -1096,7 +1096,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 39 | @Override 40 | public void handleJigsawGenerate(ServerboundJigsawGeneratePacket packet) { 41 | PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); 42 | - if (this.player.canUseGameMasterBlocks()) { 43 | + if (this.player.canUseGameMasterBlocks() && this.player.level().isLoadedAndInBounds(packet.getPos())) { // Scissors 44 | BlockPos blockposition = packet.getPos(); 45 | BlockEntity tileentity = this.player.level().getBlockEntity(blockposition); 46 | 47 | -------------------------------------------------------------------------------- /patches/server/0050-Add-depth-limit-to-updateCustomBlockEntityTag.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Focusvity 3 | Date: Sun, 11 Feb 2024 19:44:20 +1100 4 | Subject: [PATCH] Add depth limit to updateCustomBlockEntityTag 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java 8 | index 8d2c0accadaf0c5d28e7db6e62a05f6c619cf02f..75d31897711cf5917bc6f8082edddbb502c46a95 100644 9 | --- a/src/main/java/net/minecraft/world/item/BlockItem.java 10 | +++ b/src/main/java/net/minecraft/world/item/BlockItem.java 11 | @@ -4,12 +4,19 @@ import java.util.Iterator; 12 | import java.util.List; 13 | import java.util.Map; 14 | import java.util.Objects; 15 | +// Scissors start 16 | +import java.util.regex.Matcher; 17 | +import java.util.regex.Pattern; 18 | +// Scissors end 19 | import java.util.stream.Stream; 20 | import javax.annotation.Nullable; 21 | + 22 | +import me.totalfreedom.scissors.ScissorsConfig; // Scissors 23 | import net.minecraft.advancements.CriteriaTriggers; 24 | import net.minecraft.core.BlockPos; 25 | import net.minecraft.nbt.CompoundTag; 26 | import net.minecraft.nbt.ListTag; 27 | +import net.minecraft.nbt.Tag; // Scissors 28 | import net.minecraft.network.chat.Component; 29 | import net.minecraft.server.MinecraftServer; 30 | import net.minecraft.server.level.ServerLevel; 31 | @@ -240,6 +247,35 @@ public class BlockItem extends Item { 32 | if (nbttagcompound != null) { 33 | BlockEntity tileentity = world.getBlockEntity(pos); 34 | 35 | + // Scissors start 36 | + if (nbttagcompound.contains("CustomName")) { 37 | + String customName = nbttagcompound.getString("CustomName"); 38 | + Pattern EXTRA_PATTERN = Pattern.compile("\"extra\":(\\[(.*?)\\{|\\[\\{)"); 39 | + Matcher matcher = EXTRA_PATTERN.matcher(customName); 40 | + if (matcher.find()) { 41 | + String matcherString = matcher.group(); 42 | + int penalty = (matcherString.startsWith("\"extra\":[{") ? (int) matcher.results().count() : matcher.group().replace("\"extra\":", "").replace("{", "").length()) * 12; 43 | + if (penalty > ScissorsConfig.componentDepthLimit) { 44 | + return false; 45 | + } 46 | + } 47 | + } 48 | + 49 | + for (Tag tag : nbttagcompound.tags.values()) { 50 | + if (tag instanceof CompoundTag compoundTag && compoundTag.contains("messages")) { 51 | + ListTag messagesList = compoundTag.getList("messages", 8); 52 | + Pattern TRANSLATE_PLACEHOLDER_PATTERN = Pattern.compile("%[0-9]+\\$s"); 53 | + Matcher matcher = TRANSLATE_PLACEHOLDER_PATTERN.matcher(messagesList.toString()); 54 | + if (matcher.find()) { 55 | + int penalty = (int) matcher.results().count() * 12; 56 | + if (penalty > ScissorsConfig.componentDepthLimit) { 57 | + return false; 58 | + } 59 | + } 60 | + } 61 | + } 62 | + // Scissors end 63 | + 64 | if (tileentity != null) { 65 | if (!world.isClientSide && tileentity.onlyOpCanSetNbt() && (player == null || !(player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place"))))) { // Spigot - add permission 66 | return false; 67 | -------------------------------------------------------------------------------- /patches/server/0044-Add-depth-limit-to-SNBT.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Mon, 15 Apr 2024 23:40:27 -0500 4 | Subject: [PATCH] Add depth limit to SNBT 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/nbt/TagParser.java b/src/main/java/net/minecraft/nbt/TagParser.java 8 | index c77860a141064aea6a0b510bb44d35fea90aee42..3be3dd61b8a27b3a8ca3c72ae5ffa2ea8fa00231 100644 9 | --- a/src/main/java/net/minecraft/nbt/TagParser.java 10 | +++ b/src/main/java/net/minecraft/nbt/TagParser.java 11 | @@ -184,9 +184,47 @@ public class TagParser { 12 | 13 | this.expect('}'); 14 | this.depth--; // Paper 15 | - return compoundTag; 16 | + return exceedsDepthLimit(compoundTag) ? new CompoundTag() : compoundTag; // Scissors - Add depth limit to SNBT 17 | } 18 | 19 | + // Scissors start - Add depth limit to SNBT 20 | + private boolean exceedsDepthLimit(Tag tag) { 21 | + return this.exceedsDepthLimit(0, tag); 22 | + } 23 | + 24 | + private boolean exceedsDepthLimit(long depth, Tag tag) { 25 | + if (depth > 256) { 26 | + return true; 27 | + } 28 | + 29 | + if (tag instanceof ListTag listTag) { 30 | + for (Tag childTag : listTag) { 31 | + boolean returnValue = this.exceedsDepthLimit(depth + 1, childTag); 32 | + 33 | + if (returnValue) { 34 | + return true; 35 | + } 36 | + } 37 | + } else if (tag instanceof CompoundTag compoundTag) { 38 | + for (String key : compoundTag.getAllKeys()) { 39 | + Tag childTag = compoundTag.get(key); 40 | + 41 | + if (childTag == null) { 42 | + continue; 43 | + } 44 | + 45 | + boolean returnValue = this.exceedsDepthLimit(depth + 1, childTag); 46 | + 47 | + if (returnValue) { 48 | + return true; 49 | + } 50 | + } 51 | + } 52 | + 53 | + return false; 54 | + } 55 | + // Scissors end 56 | + 57 | private Tag readListTag() throws CommandSyntaxException { 58 | this.expect('['); 59 | this.reader.skipWhitespace(); 60 | @@ -220,7 +258,7 @@ public class TagParser { 61 | 62 | this.expect(']'); 63 | this.depth--; // Paper 64 | - return listTag; 65 | + return exceedsDepthLimit(listTag) ? new ListTag() : listTag; // Scissors - Add depth limit to SNBT 66 | } 67 | } 68 | 69 | @@ -245,7 +283,7 @@ public class TagParser { 70 | } 71 | 72 | private List readArray(TagType arrayTypeReader, TagType typeReader) throws CommandSyntaxException { 73 | - List list = Lists.newArrayList(); 74 | + List list = Lists.newArrayList(); // Scissors - List -> List 75 | 76 | while (this.reader.peek() != ']') { 77 | int i = this.reader.getCursor(); 78 | @@ -257,11 +295,11 @@ public class TagParser { 79 | } 80 | 81 | if (typeReader == ByteTag.TYPE) { 82 | - list.add((T)(Byte)((NumericTag)tag).getAsByte()); // Paper - decompile fix 83 | + list.add(((NumericTag)tag).getAsByte()); // Scissors - Remove (T) cast 84 | } else if (typeReader == LongTag.TYPE) { 85 | - list.add((T)(Long)((NumericTag)tag).getAsLong()); // Paper - decompile fix 86 | + list.add(((NumericTag)tag).getAsLong()); // Scissors - Remove (T) cast 87 | } else { 88 | - list.add((T)(Integer)((NumericTag)tag).getAsInt()); // Paper - decompile fix 89 | + list.add(((NumericTag)tag).getAsInt()); // Scissors - Remove (T) cast 90 | } 91 | 92 | if (!this.hasElementSeparator()) { 93 | @@ -274,7 +312,7 @@ public class TagParser { 94 | } 95 | 96 | this.expect(']'); 97 | - return list; 98 | + return (List) list; // Scissors - Cast to List 99 | } 100 | 101 | private boolean hasElementSeparator() { 102 | -------------------------------------------------------------------------------- /patches/server/0030-Prevent-velocity-freeze.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Sun, 10 Dec 2023 18:41:18 -0600 4 | Subject: [PATCH] Prevent velocity freeze 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java 8 | index 20ce474b72894a8bb3fc21018b9d79bbdc8bb14b..b5c87bb5f5d3526600520913f04cfc6614a62b81 100644 9 | --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java 10 | +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java 11 | @@ -1,6 +1,8 @@ 12 | package net.minecraft.world.entity.projectile; 13 | 14 | import javax.annotation.Nullable; 15 | + 16 | +import me.totalfreedom.scissors.MathUtility; 17 | import net.minecraft.core.particles.ParticleOptions; 18 | import net.minecraft.core.particles.ParticleTypes; 19 | import net.minecraft.nbt.CompoundTag; 20 | @@ -50,12 +52,15 @@ public abstract class AbstractHurtingProjectile extends Projectile { 21 | // CraftBukkit end 22 | double d6 = Math.sqrt(d3 * d3 + d4 * d4 + d5 * d5); 23 | 24 | - if (d6 != 0.0D) { 25 | - this.xPower = d3 / d6 * 0.1D; 26 | - this.yPower = d4 / d6 * 0.1D; 27 | - this.zPower = d5 / d6 * 0.1D; 28 | + if (d6 != 0.0D) 29 | + { 30 | + // Scissors start - Prevent projectile velocity freeze 31 | + //this.xPower = d3 / d6 * 0.1D; 32 | + //this.yPower = d4 / d6 * 0.1D; 33 | + //this.zPower = d5 / d6 * 0.1D; 34 | + setPower(d3 / d6 * .1d, d4 / d6 * .1d, d5 / d6 * .1d); 35 | } 36 | - 37 | + // Scissors end 38 | } 39 | 40 | public AbstractHurtingProjectile(EntityType type, LivingEntity owner, double directionX, double directionY, double directionZ, Level world) { 41 | @@ -167,6 +172,25 @@ public abstract class AbstractHurtingProjectile extends Projectile { 42 | nbt.put("power", this.newDoubleList(new double[]{this.xPower, this.yPower, this.zPower})); 43 | } 44 | 45 | + // Scissors start - Prevent projectile velocity freeze 46 | + public void setPower(double xPower, double yPower, double zPower) 47 | + { 48 | + if (Double.isInfinite(xPower) || Double.isInfinite(yPower) || Double.isInfinite(zPower)) 49 | + { 50 | + return; 51 | + } 52 | + 53 | + if (Double.isNaN(xPower) || Double.isNaN(yPower) || Double.isNaN(zPower)) 54 | + { 55 | + return; 56 | + } 57 | + 58 | + this.xPower = MathUtility.clampDouble(xPower, -1024, 1024); 59 | + this.yPower = MathUtility.clampDouble(yPower, -1024, 1024); 60 | + this.zPower = MathUtility.clampDouble(zPower, -1024, 1024); 61 | + } 62 | + // Scissors end 63 | + 64 | @Override 65 | public void readAdditionalSaveData(CompoundTag nbt) { 66 | super.readAdditionalSaveData(nbt); 67 | @@ -174,9 +198,13 @@ public abstract class AbstractHurtingProjectile extends Projectile { 68 | ListTag nbttaglist = nbt.getList("power", 6); 69 | 70 | if (nbttaglist.size() == 3) { 71 | - this.xPower = nbttaglist.getDouble(0); 72 | - this.yPower = nbttaglist.getDouble(1); 73 | - this.zPower = nbttaglist.getDouble(2); 74 | + // Scissors start - Prevent projectile velocity freeze 75 | + //this.xPower = nbttaglist.getDouble(0); 76 | + //this.yPower = nbttaglist.getDouble(1); 77 | + //this.zPower = nbttaglist.getDouble(2); 78 | + 79 | + setPower(nbttaglist.getDouble(0), nbttaglist.getDouble(1), nbttaglist.getDouble(2)); 80 | + // Scissors end 81 | } 82 | } 83 | 84 | @@ -210,9 +238,13 @@ public abstract class AbstractHurtingProjectile extends Projectile { 85 | Vec3 vec3d = entity.getLookAngle(); 86 | 87 | this.setDeltaMovement(vec3d); 88 | - this.xPower = vec3d.x * 0.1D; 89 | - this.yPower = vec3d.y * 0.1D; 90 | - this.zPower = vec3d.z * 0.1D; 91 | + // Scissors start - Prevent projectile velocity freeze 92 | + //this.xPower = vec3d.x * 0.1D; 93 | + //this.yPower = vec3d.y * 0.1D; 94 | + //this.zPower = vec3d.z * 0.1D; 95 | + 96 | + setPower(vec3d.x * 0.1D, vec3d.y * 0.1D, vec3d.z * 0.1D); 97 | + // Scissors end 98 | this.setOwner(entity); 99 | } 100 | 101 | -------------------------------------------------------------------------------- /patches/server/0031-Patch-large-selector-distance-crash.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Sun, 10 Dec 2023 18:57:50 -0600 4 | Subject: [PATCH] Patch large selector distance crash 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/advancements/critereon/MinMaxBounds.java b/src/main/java/net/minecraft/advancements/critereon/MinMaxBounds.java 8 | index f62640152027b874d4266d868574af062bd684d7..f94385837d5ed1ef52458b73410df5fd186d66e2 100644 9 | --- a/src/main/java/net/minecraft/advancements/critereon/MinMaxBounds.java 10 | +++ b/src/main/java/net/minecraft/advancements/critereon/MinMaxBounds.java 11 | @@ -123,11 +123,11 @@ public interface MinMaxBounds { 12 | public static record Doubles(@Override Optional min, @Override Optional max, Optional minSq, Optional maxSq) 13 | implements MinMaxBounds { 14 | public static final MinMaxBounds.Doubles ANY = new MinMaxBounds.Doubles(Optional.empty(), Optional.empty()); 15 | - public static final Codec CODEC = MinMaxBounds.createCodec(Codec.DOUBLE, MinMaxBounds.Doubles::new); 16 | + public static final Codec CODEC = MinMaxBounds.createCodec(Codec.DOUBLE, MinMaxBounds.Doubles::new); // Scissors - compile fixes 17 | 18 | - private Doubles(Optional min, Optional max) { 19 | + public Doubles(Optional min, Optional max) { 20 | this(min, max, squareOpt(min), squareOpt(max)); 21 | - } 22 | + } // Scissors - private -> public 23 | 24 | private static MinMaxBounds.Doubles create(StringReader reader, Optional min, Optional max) throws CommandSyntaxException { 25 | if (min.isPresent() && max.isPresent() && min.get() > max.get()) { 26 | @@ -179,7 +179,7 @@ public interface MinMaxBounds { 27 | public static record Ints(@Override Optional min, @Override Optional max, Optional minSq, Optional maxSq) 28 | implements MinMaxBounds { 29 | public static final MinMaxBounds.Ints ANY = new MinMaxBounds.Ints(Optional.empty(), Optional.empty()); 30 | - public static final Codec CODEC = MinMaxBounds.createCodec(Codec.INT, MinMaxBounds.Ints::new); 31 | + public static final Codec CODEC = MinMaxBounds.createCodec(Codec.INT, MinMaxBounds.Ints::new); // Scissors - compile fixes 32 | 33 | private Ints(Optional min, Optional max) { 34 | this(min, max, min.map(i -> i.longValue() * i.longValue()), squareOpt(max)); 35 | diff --git a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java 36 | index 676a1499747b071515479130875157263d3a8352..6a65850101b8ea348a4bfeaeca805a39987b06fc 100644 37 | --- a/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java 38 | +++ b/src/main/java/net/minecraft/commands/arguments/selector/EntitySelector.java 39 | @@ -10,6 +10,8 @@ import java.util.function.BiConsumer; 40 | import java.util.function.Function; 41 | import java.util.function.Predicate; 42 | import javax.annotation.Nullable; 43 | + 44 | +import me.totalfreedom.scissors.MathUtility; 45 | import net.minecraft.advancements.critereon.MinMaxBounds; 46 | import net.minecraft.commands.CommandSourceStack; 47 | import net.minecraft.commands.arguments.EntityArgument; 48 | @@ -60,9 +62,26 @@ public class EntitySelector { 49 | this.includesEntities = includesNonPlayers; 50 | this.worldLimited = localWorldOnly; 51 | this.predicate = basePredicate; 52 | - this.range = distance; 53 | + // Scissors start - Patch large selector distance crash 54 | + this.range = new MinMaxBounds.Doubles( 55 | + distance.min().map(min -> Math.min(min, 1024)), 56 | + distance.max().map(max -> Math.min(max, 1024)) 57 | + ); 58 | this.position = positionOffset; 59 | - this.aabb = box; 60 | + if (box != null) { 61 | + this.aabb = new AABB( 62 | + MathUtility.clampDouble(box.minX, -1024, 1025), 63 | + MathUtility.clampDouble(box.minY, -1024, 1025), 64 | + MathUtility.clampDouble(box.minZ, -1024, 1025), 65 | + MathUtility.clampDouble(box.maxX, -1024, 1025), 66 | + MathUtility.clampDouble(box.maxY, -1024, 1025), 67 | + MathUtility.clampDouble(box.maxZ, -1024, 1025), 68 | + false 69 | + ); 70 | + } else { 71 | + this.aabb = null; 72 | + } 73 | + // Scissors end 74 | this.order = sorter; 75 | this.currentEntity = senderOnly; 76 | this.playerName = playerName; 77 | -------------------------------------------------------------------------------- /patches/server/0042-Implement-command-block-events.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Mon, 15 Apr 2024 23:27:16 -0500 4 | Subject: [PATCH] Implement command block events 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCommandMinecartPacket.java b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCommandMinecartPacket.java 8 | index c99fc118013cb3d4043638e2001a8297e79ddf9c..cdaa81e1f2167b29ec01cc25e51a8400deb533d2 100644 9 | --- a/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCommandMinecartPacket.java 10 | +++ b/src/main/java/net/minecraft/network/protocol/game/ServerboundSetCommandMinecartPacket.java 11 | @@ -9,7 +9,7 @@ import net.minecraft.world.level.BaseCommandBlock; 12 | import net.minecraft.world.level.Level; 13 | 14 | public class ServerboundSetCommandMinecartPacket implements Packet { 15 | - private final int entity; 16 | + public final int entity; // Scissors - private -> public 17 | private final String command; 18 | private final boolean trackOutput; 19 | 20 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 21 | index 843793437737305bbdec598326a813f84b820d12..bbe76d46b599fb2f8211f3e62a76430db120f66f 100644 22 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 23 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 24 | @@ -1,6 +1,8 @@ 25 | package net.minecraft.server.network; 26 | 27 | import me.totalfreedom.scissors.ScissorsConfig; 28 | +import me.totalfreedom.scissors.event.block.CommandBlockPlayerEditEvent; 29 | +import me.totalfreedom.scissors.event.block.CommandMinecartPlayerEditEvent; 30 | import me.totalfreedom.scissors.event.player.SpectatorTeleportEvent; // Scissors 31 | import com.google.common.collect.Lists; 32 | import com.google.common.primitives.Floats; 33 | @@ -155,6 +157,7 @@ import net.minecraft.world.entity.player.Inventory; 34 | import net.minecraft.world.entity.player.ProfilePublicKey; 35 | import net.minecraft.world.entity.projectile.AbstractArrow; 36 | import net.minecraft.world.entity.vehicle.Boat; 37 | +import net.minecraft.world.entity.vehicle.MinecartCommandBlock; 38 | import net.minecraft.world.inventory.AbstractContainerMenu; 39 | import net.minecraft.world.inventory.AnvilMenu; 40 | import net.minecraft.world.inventory.BeaconMenu; 41 | @@ -189,6 +192,8 @@ import net.minecraft.world.phys.Vec3; 42 | import net.minecraft.world.phys.shapes.BooleanOp; 43 | import net.minecraft.world.phys.shapes.Shapes; 44 | import net.minecraft.world.phys.shapes.VoxelShape; 45 | +import org.bukkit.craftbukkit.block.CraftCommandBlock; 46 | +import org.bukkit.craftbukkit.entity.CraftMinecartCommand; 47 | import org.slf4j.Logger; 48 | 49 | // CraftBukkit start 50 | @@ -905,6 +910,16 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 51 | this.player.level().getChunkAt(blockposition).setBlockEntity(tileentity); 52 | } 53 | 54 | + // Scissors start 55 | + CommandBlockPlayerEditEvent event = new CommandBlockPlayerEditEvent(this.getCraftPlayer(), commandblocklistenerabstract.getCommand(), s, new CraftCommandBlock(this.player.level().getWorld(), tileentitycommand)); 56 | + 57 | + if (!event.callEvent()) { 58 | + return; 59 | + } 60 | + 61 | + s = event.getNewCommand(); 62 | + // Scissors end 63 | + 64 | commandblocklistenerabstract.setCommand(s); 65 | commandblocklistenerabstract.setTrackOutput(flag); 66 | if (!flag) { 67 | @@ -936,7 +951,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 68 | BaseCommandBlock commandblocklistenerabstract = packet.getCommandBlock(this.player.level()); 69 | 70 | if (commandblocklistenerabstract != null) { 71 | - commandblocklistenerabstract.setCommand(packet.getCommand()); 72 | + // Scissors start - Implement command block events 73 | + String command = packet.getCommand(); 74 | + CommandMinecartPlayerEditEvent event = new CommandMinecartPlayerEditEvent(this.getCraftPlayer(), commandblocklistenerabstract.getCommand(), command, new CraftMinecartCommand(this.cserver, (MinecartCommandBlock) this.player.level().getEntity(packet.entity))); 75 | + 76 | + if (!event.callEvent()) { 77 | + return; 78 | + } 79 | + 80 | + command = event.getNewCommand(); 81 | + commandblocklistenerabstract.setCommand(command); 82 | + // Scissors end 83 | commandblocklistenerabstract.setTrackOutput(packet.isTrackOutput()); 84 | if (!packet.isTrackOutput()) { 85 | commandblocklistenerabstract.setLastOutput((Component) null); 86 | -------------------------------------------------------------------------------- /patches/server/0048-Change-version-fetcher-to-AMG.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Tue, 23 Jan 2024 19:01:02 -0600 4 | Subject: [PATCH] Change version fetcher to AMG 5 | 6 | 7 | diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java 8 | index 9d687da5bdf398bb3f6c84cdf1249a7213d09f2e..48dd50d0e443a59835e92616874c9856c7cbc401 100644 9 | --- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java 10 | +++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java 11 | @@ -4,6 +4,7 @@ import com.destroystokyo.paper.util.VersionFetcher; 12 | import com.google.common.base.Charsets; 13 | import com.google.common.io.Resources; 14 | import com.google.gson.*; 15 | +import io.papermc.paper.util.JarManifests; // Scissors 16 | import net.kyori.adventure.text.Component; 17 | import net.kyori.adventure.text.event.ClickEvent; 18 | import net.kyori.adventure.text.format.NamedTextColor; 19 | @@ -16,11 +17,12 @@ import java.io.*; 20 | import java.net.HttpURLConnection; 21 | import java.net.URL; 22 | import java.util.stream.StreamSupport; 23 | +import org.bukkit.Bukkit; // Scissors 24 | 25 | public class PaperVersionFetcher implements VersionFetcher { 26 | private static final java.util.regex.Pattern VER_PATTERN = java.util.regex.Pattern.compile("^([0-9\\.]*)\\-.*R"); // R is an anchor, will always give '-R' at end 27 | - private static final String GITHUB_BRANCH_NAME = "master"; 28 | - private static final String DOWNLOAD_PAGE = "https://papermc.io/downloads/paper"; 29 | + private static final String GITHUB_BRANCH_NAME = getBranch(); // Scissors 30 | + private static final String DOWNLOAD_PAGE = "https://ci.scissors.gg/job/Scissors/job/" + GITHUB_BRANCH_NAME; // Scissors 31 | private static @Nullable String mcVer; 32 | 33 | @Override 34 | @@ -31,8 +33,8 @@ public class PaperVersionFetcher implements VersionFetcher { 35 | @Nonnull 36 | @Override 37 | public Component getVersionMessage(@Nonnull String serverVersion) { 38 | - String[] parts = serverVersion.substring("git-Paper-".length()).split("[-\\s]"); 39 | - final Component updateMessage = getUpdateStatusMessage("PaperMC/Paper", GITHUB_BRANCH_NAME, parts[0]); 40 | + String[] parts = serverVersion.substring("git-Scissors-".length()).split("[-\\s]"); // Scissors 41 | + final Component updateMessage = getUpdateStatusMessage("AtlasMediaGroup/Scissors", GITHUB_BRANCH_NAME, parts[0]); // Scissors 42 | final Component history = getHistory(); 43 | 44 | return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage; 45 | @@ -54,15 +56,24 @@ public class PaperVersionFetcher implements VersionFetcher { 46 | return mcVer; 47 | } 48 | 49 | + // Scissors start - Allow getting git information 50 | + public static String getCommit() { 51 | + final var manifest = JarManifests.manifest(Bukkit.getServer().getClass()); 52 | + return manifest == null ? null : manifest.getMainAttributes().getValue("Git-Commit"); 53 | + } 54 | + 55 | + public static String getBranch() { 56 | + final var manifest = JarManifests.manifest(Bukkit.getServer().getClass()); 57 | + return manifest == null ? null : manifest.getMainAttributes().getValue("Git-Branch"); 58 | + } 59 | + // Scissors end 60 | + 61 | private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) { 62 | int distance; 63 | - try { 64 | - int jenkinsBuild = Integer.parseInt(versionInfo); 65 | - distance = fetchDistanceFromSiteApi(jenkinsBuild, getMinecraftVersion()); 66 | - } catch (NumberFormatException ignored) { 67 | - versionInfo = versionInfo.replace("\"", ""); 68 | - distance = fetchDistanceFromGitHub(repo, branch, versionInfo); 69 | - } 70 | + // Scissors start - always use Git for version checking 71 | + versionInfo = getCommit(); 72 | + distance = fetchDistanceFromGitHub(repo, branch, versionInfo); 73 | + // Scissors end 74 | 75 | switch (distance) { 76 | case -1: 77 | diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java 78 | index c0538206a53f0e6d9b54bddde0259b89ac73d675..5ebb80ed81d9bbd4c69a14ccd0be6c67de2fcf0d 100644 79 | --- a/src/main/java/org/bukkit/craftbukkit/Main.java 80 | +++ b/src/main/java/org/bukkit/craftbukkit/Main.java 81 | @@ -315,7 +315,7 @@ public class Main { 82 | if (buildDate.before(deadline.getTime())) { 83 | // Paper start - This is some stupid bullshit 84 | System.err.println("*** Warning, you've not updated in a while! ***"); 85 | - System.err.println("*** Please download a new build as per instructions from https://papermc.io/downloads/paper ***"); // Paper 86 | + System.err.println("*** Please download a new build as per instructions from https://ci.scissors.gg/job/Scissors ***"); // Paper 87 | //System.err.println("*** Server will start in 20 seconds ***"); 88 | //Thread.sleep(TimeUnit.SECONDS.toMillis(20)); 89 | // Paper end 90 | -------------------------------------------------------------------------------- /patches/server/0049-Add-depth-limit-to-Component-deserialization.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Focusvity 3 | Date: Mon, 5 Feb 2024 19:39:23 +1100 4 | Subject: [PATCH] Add depth limit to Component deserialization 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java 8 | index ae84d06564b2560e13404f6d89f88ad71dbc2cc6..df3c03aeaee5c12c5d57584535c9c7aa01be7dd3 100644 9 | --- a/src/main/java/net/minecraft/network/chat/Component.java 10 | +++ b/src/main/java/net/minecraft/network/chat/Component.java 11 | @@ -3,9 +3,11 @@ package net.minecraft.network.chat; 12 | import com.google.common.collect.Lists; 13 | import com.google.gson.Gson; 14 | import com.google.gson.GsonBuilder; 15 | +import com.google.gson.JsonArray; 16 | import com.google.gson.JsonDeserializationContext; 17 | import com.google.gson.JsonDeserializer; 18 | import com.google.gson.JsonElement; 19 | +import com.google.gson.JsonObject; 20 | import com.google.gson.JsonParseException; 21 | import com.google.gson.JsonParser; 22 | import com.google.gson.JsonSerializationContext; 23 | @@ -13,6 +15,7 @@ import com.google.gson.JsonSerializer; 24 | import com.google.gson.stream.JsonReader; 25 | import com.mojang.brigadier.Message; 26 | import com.mojang.serialization.JsonOps; 27 | + 28 | import java.io.StringReader; 29 | import java.lang.reflect.Type; 30 | import java.util.ArrayList; 31 | @@ -23,6 +26,9 @@ import java.util.List; 32 | import java.util.Optional; 33 | import java.util.UUID; 34 | import javax.annotation.Nullable; 35 | + 36 | +import me.totalfreedom.scissors.ScissorsConfig; // Scissors 37 | +import net.minecraft.ChatFormatting; 38 | import net.minecraft.Util; 39 | import net.minecraft.network.chat.contents.DataSource; 40 | import net.minecraft.network.chat.contents.KeybindContents; 41 | @@ -33,8 +39,10 @@ import net.minecraft.network.chat.contents.SelectorContents; 42 | import net.minecraft.network.chat.contents.TranslatableContents; 43 | import net.minecraft.resources.ResourceLocation; 44 | import net.minecraft.util.FormattedCharSequence; 45 | +import net.minecraft.util.GsonHelper; 46 | import net.minecraft.world.level.ChunkPos; 47 | // CraftBukkit start 48 | +import java.util.regex.Pattern; // Scissors 49 | import java.util.stream.Stream; 50 | // CraftBukkit end 51 | 52 | @@ -284,10 +292,65 @@ public interface Component extends Message, FormattedText, Iterable { 53 | public static class Serializer { 54 | 55 | private static final Gson GSON = (new GsonBuilder()).disableHtmlEscaping().create(); 56 | + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("%[0-9]+\\$s"); // Scissors 57 | 58 | private Serializer() {} 59 | 60 | + // Scissors start 61 | + static int depthChecker(int depth) { 62 | + depth = depth + 1; 63 | + if (depth > ScissorsConfig.componentDepthLimit) { 64 | + throw new JsonParseException("Depth limit exceeded"); 65 | + } 66 | + return depth; 67 | + } 68 | + 69 | + static int getPenalty(String string) { 70 | + if (PLACEHOLDER_PATTERN.matcher(string).find()) { 71 | + long translate_placeholders = PLACEHOLDER_PATTERN.matcher(string).results().count(); 72 | + return (int) translate_placeholders * 12; 73 | + } 74 | + return 0; 75 | + } 76 | + 77 | static MutableComponent deserialize(JsonElement json) { 78 | + int depth = 1; 79 | + if (!json.isJsonPrimitive()) { 80 | + if (!json.isJsonObject()) { 81 | + if (json.isJsonArray()) { 82 | + JsonArray jsonArray = json.getAsJsonArray(); 83 | + if (jsonArray.size() <= 0) throw new JsonParseException("Unexpected empty array of components"); 84 | + 85 | + for (JsonElement ignored : jsonArray) { 86 | + depth = depthChecker(depth); 87 | + } 88 | + } 89 | + } else { 90 | + JsonObject jsonObject = json.getAsJsonObject(); 91 | + if (jsonObject.has("translate")) { 92 | + String s = GsonHelper.getAsString(jsonObject, "translate"); 93 | + int penalty = getPenalty(s); 94 | + depth = depthChecker(depth + penalty); 95 | + 96 | + if (jsonObject.has("with")) { 97 | + String s1 = GsonHelper.getAsJsonArray(jsonObject, "with").toString(); 98 | + penalty = getPenalty(s1); 99 | + depth = depthChecker(depth + penalty); 100 | + } 101 | + } 102 | + 103 | + if (jsonObject.has("extra")) { 104 | + JsonArray jsonArray = GsonHelper.getAsJsonArray(jsonObject, "extra"); 105 | + if (jsonArray.size() <= 0) throw new JsonParseException("Unexpected empty array of components"); 106 | + 107 | + for (JsonElement ignored : jsonArray) { 108 | + depth = depthChecker(depth); 109 | + } 110 | + } 111 | + } 112 | + } 113 | + // Scissors end 114 | + 115 | return (MutableComponent) Util.getOrThrow(ComponentSerialization.CODEC.parse(JsonOps.INSTANCE, json), JsonParseException::new); 116 | } 117 | 118 | -------------------------------------------------------------------------------- /patches/api/0004-Add-command-block-player-edit-event.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Fri, 2 Jun 2023 20:42:02 +0100 4 | Subject: [PATCH] Add command block player edit event 5 | 6 | 7 | diff --git a/src/main/java/me/totalfreedom/scissors/event/block/CommandBlockPlayerEditEvent.java b/src/main/java/me/totalfreedom/scissors/event/block/CommandBlockPlayerEditEvent.java 8 | new file mode 100644 9 | index 0000000000000000000000000000000000000000..722f5839600954998cbbf799e68477d499d104c4 10 | --- /dev/null 11 | +++ b/src/main/java/me/totalfreedom/scissors/event/block/CommandBlockPlayerEditEvent.java 12 | @@ -0,0 +1,77 @@ 13 | +package me.totalfreedom.scissors.event.block; 14 | + 15 | +import org.bukkit.block.CommandBlock; 16 | +import org.bukkit.entity.Player; 17 | +import org.bukkit.event.Cancellable; 18 | +import org.bukkit.event.Event; 19 | +import org.bukkit.event.HandlerList; 20 | +import org.jetbrains.annotations.NotNull; 21 | + 22 | +/** 23 | + * Called when a command block is modified by a player 24 | + */ 25 | +public class CommandBlockPlayerEditEvent extends Event implements Cancellable 26 | +{ 27 | + private static final HandlerList handlers = new HandlerList(); 28 | + private boolean cancelled; 29 | + private final Player player; 30 | + private final String oldCommand; 31 | + private String newCommand; 32 | + private final CommandBlock commandBlock; 33 | + 34 | + public CommandBlockPlayerEditEvent(@NotNull Player player, @NotNull String oldCommand, @NotNull String newCommand, @NotNull CommandBlock commandBlock) 35 | + { 36 | + this.player = player; 37 | + this.oldCommand = oldCommand; 38 | + this.newCommand = newCommand; 39 | + this.commandBlock = commandBlock; 40 | + } 41 | + 42 | + public @NotNull String getNewCommand() 43 | + { 44 | + return this.newCommand; 45 | + } 46 | + 47 | + public @NotNull String getOldCommand() 48 | + { 49 | + return this.oldCommand; 50 | + } 51 | + 52 | + public void setNewCommand(@NotNull String newCommand) 53 | + { 54 | + this.newCommand = newCommand; 55 | + } 56 | + 57 | + public @NotNull Player getPlayer() 58 | + { 59 | + return this.player; 60 | + } 61 | + 62 | + public @NotNull CommandBlock getCommandBlock() 63 | + { 64 | + return this.commandBlock; 65 | + } 66 | + 67 | + @Override 68 | + public boolean isCancelled() 69 | + { 70 | + return this.cancelled; 71 | + } 72 | + 73 | + @Override 74 | + public void setCancelled(boolean cancel) 75 | + { 76 | + this.cancelled = cancel; 77 | + } 78 | + 79 | + @Override 80 | + public @NotNull HandlerList getHandlers() 81 | + { 82 | + return handlers; 83 | + } 84 | + 85 | + public static @NotNull HandlerList getHandlerList() 86 | + { 87 | + return handlers; 88 | + } 89 | +} 90 | diff --git a/src/main/java/me/totalfreedom/scissors/event/block/CommandMinecartPlayerEditEvent.java b/src/main/java/me/totalfreedom/scissors/event/block/CommandMinecartPlayerEditEvent.java 91 | new file mode 100644 92 | index 0000000000000000000000000000000000000000..4282f24deb87e52ee19a13b172ec80c6a6017e28 93 | --- /dev/null 94 | +++ b/src/main/java/me/totalfreedom/scissors/event/block/CommandMinecartPlayerEditEvent.java 95 | @@ -0,0 +1,78 @@ 96 | +package me.totalfreedom.scissors.event.block; 97 | + 98 | +import org.bukkit.block.CommandBlock; 99 | +import org.bukkit.entity.Player; 100 | +import org.bukkit.entity.minecart.CommandMinecart; 101 | +import org.bukkit.event.Cancellable; 102 | +import org.bukkit.event.Event; 103 | +import org.bukkit.event.HandlerList; 104 | +import org.jetbrains.annotations.NotNull; 105 | + 106 | +/** 107 | + * Called when a command block is modified by a player 108 | + */ 109 | +public class CommandMinecartPlayerEditEvent extends Event implements Cancellable 110 | +{ 111 | + private static final HandlerList handlers = new HandlerList(); 112 | + private boolean cancelled; 113 | + private final Player player; 114 | + private final String oldCommand; 115 | + private String newCommand; 116 | + private final CommandMinecart commandMinecart; 117 | + 118 | + public CommandMinecartPlayerEditEvent(@NotNull Player player, @NotNull String oldCommand, @NotNull String newCommand, @NotNull CommandMinecart commandMinecart) 119 | + { 120 | + this.player = player; 121 | + this.oldCommand = oldCommand; 122 | + this.newCommand = newCommand; 123 | + this.commandMinecart = commandMinecart; 124 | + } 125 | + 126 | + public @NotNull String getNewCommand() 127 | + { 128 | + return this.newCommand; 129 | + } 130 | + 131 | + public @NotNull String getOldCommand() 132 | + { 133 | + return this.oldCommand; 134 | + } 135 | + 136 | + public void setNewCommand(@NotNull String newCommand) 137 | + { 138 | + this.newCommand = newCommand; 139 | + } 140 | + 141 | + public @NotNull Player getPlayer() 142 | + { 143 | + return this.player; 144 | + } 145 | + 146 | + public @NotNull CommandMinecart getCommandMinecart() 147 | + { 148 | + return this.commandMinecart; 149 | + } 150 | + 151 | + @Override 152 | + public boolean isCancelled() 153 | + { 154 | + return this.cancelled; 155 | + } 156 | + 157 | + @Override 158 | + public void setCancelled(boolean cancel) 159 | + { 160 | + this.cancelled = cancel; 161 | + } 162 | + 163 | + @Override 164 | + public @NotNull HandlerList getHandlers() 165 | + { 166 | + return handlers; 167 | + } 168 | + 169 | + public static @NotNull HandlerList getHandlerList() 170 | + { 171 | + return handlers; 172 | + } 173 | +} 174 | -------------------------------------------------------------------------------- /patches/server/0018-Limit-amount-of-vehicle-collision-checks-to-3-and-di.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Thu, 21 Apr 2022 13:52:32 +0100 4 | Subject: [PATCH] Limit amount of vehicle collision checks to 3 and discard 5 | vehicles if they collide with more than 15 other entities 6 | 7 | 8 | diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java 9 | index d514ec1e4cbdc579c3a61533998437903afdc8b6..7ee1f3552b81bff834c6f414e611e8b05463fc6f 100644 10 | --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java 11 | +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java 12 | @@ -8,6 +8,7 @@ import com.mojang.datafixers.util.Pair; 13 | import java.util.Iterator; 14 | import java.util.List; 15 | import java.util.Map; 16 | +import java.util.concurrent.TimeUnit; // Scissors 17 | import javax.annotation.Nullable; 18 | import net.minecraft.BlockUtil; 19 | import net.minecraft.Util; 20 | @@ -104,6 +105,7 @@ public abstract class AbstractMinecart extends VehicleEntity { 21 | private double flyingX = 0.95; 22 | private double flyingY = 0.95; 23 | private double flyingZ = 0.95; 24 | + private long lastLargeCollision = 0L; // Scissors - Add a collision debounce 25 | public double maxSpeed = 0.4D; 26 | // CraftBukkit end 27 | 28 | @@ -384,8 +386,8 @@ public abstract class AbstractMinecart extends VehicleEntity { 29 | if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { 30 | List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D), EntitySelector.pushableBy(this)); 31 | 32 | - if (!list.isEmpty()) { 33 | - Iterator iterator = list.iterator(); 34 | + if (!list.isEmpty() && (System.currentTimeMillis() - lastLargeCollision) >= TimeUnit.SECONDS.toMillis(5)) { // Scissors - add collision debounce, using TimeUnit for better code readability 35 | + Iterator iterator = list.size() <= 15 ? list.iterator() : list.subList(0, 15).iterator(); // Scissors 36 | 37 | while (iterator.hasNext()) { 38 | Entity entity = (Entity) iterator.next(); 39 | @@ -414,6 +416,14 @@ public abstract class AbstractMinecart extends VehicleEntity { 40 | entity.push(this); 41 | } 42 | } 43 | + 44 | + // Scissors start - Add a collision debounce 45 | + if (list.size() > 15) { 46 | + this.discard(null); 47 | + } else if (list.size() > 3) { 48 | + lastLargeCollision = System.currentTimeMillis(); 49 | + } 50 | + // Scissors end 51 | } 52 | } else { 53 | Iterator iterator1 = this.level().getEntities(this, this.getBoundingBox().inflate(0.20000000298023224D, 0.0D, 0.20000000298023224D)).iterator(); 54 | diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java 55 | index db6aa75d642f4a7258f197933671907faf79c8f2..e4490494a865e129c69d7df3742f61860763a8d8 100644 56 | --- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java 57 | +++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java 58 | @@ -5,6 +5,7 @@ import com.google.common.collect.UnmodifiableIterator; 59 | import java.util.Iterator; 60 | import java.util.List; 61 | import java.util.function.IntFunction; 62 | +import java.util.concurrent.TimeUnit; // Scissors 63 | import javax.annotation.Nullable; 64 | import net.minecraft.BlockUtil; 65 | import net.minecraft.core.BlockPos; 66 | @@ -108,6 +109,7 @@ public class Boat extends VehicleEntity implements VariantHolder { 67 | public double unoccupiedDeceleration = -1; 68 | public boolean landBoats = false; 69 | // CraftBukkit end 70 | + private long lastLargeCollision = 0L; // Scissors - Add a collision debounce 71 | 72 | public Boat(EntityType type, Level world) { 73 | super(type, world); 74 | @@ -408,9 +410,9 @@ public class Boat extends VehicleEntity implements VariantHolder { 75 | this.checkInsideBlocks(); 76 | List list = this.level().getEntities((Entity) this, this.getBoundingBox().inflate(0.20000000298023224D, -0.009999999776482582D, 0.20000000298023224D), EntitySelector.pushableBy(this)); 77 | 78 | - if (!list.isEmpty()) { 79 | + if (!list.isEmpty() && (System.currentTimeMillis() - lastLargeCollision) >= TimeUnit.SECONDS.toMillis(5)) { // Scissors - add collision debounce, using TimeUnit for better code readability 80 | boolean flag = !this.level().isClientSide && !(this.getControllingPassenger() instanceof Player); 81 | - Iterator iterator = list.iterator(); 82 | + Iterator iterator = list.size() <= 15 ? list.iterator() : list.subList(0, 15).iterator(); // Scissors 83 | 84 | while (iterator.hasNext()) { 85 | Entity entity = (Entity) iterator.next(); 86 | @@ -423,6 +425,14 @@ public class Boat extends VehicleEntity implements VariantHolder { 87 | } 88 | } 89 | } 90 | + 91 | + // Scissors start - Add collision debounce 92 | + if (list.size() > 15) { 93 | + this.discard(null); 94 | + } else if (list.size() > 3) { 95 | + lastLargeCollision = System.currentTimeMillis(); 96 | + } 97 | + // Scissors end 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /patches/server/0019-Add-custom-classes-used-by-Scissors.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Sat, 11 Jun 2022 22:56:59 -0500 4 | Subject: [PATCH] Add custom classes used by Scissors 5 | 6 | 7 | diff --git a/src/main/java/me/totalfreedom/scissors/MathUtility.java b/src/main/java/me/totalfreedom/scissors/MathUtility.java 8 | new file mode 100644 9 | index 0000000000000000000000000000000000000000..754b578b575137a9c48cb20dee965a9388fedb3c 10 | --- /dev/null 11 | +++ b/src/main/java/me/totalfreedom/scissors/MathUtility.java 12 | @@ -0,0 +1,29 @@ 13 | +package me.totalfreedom.scissors; 14 | + 15 | +public class MathUtility 16 | +{ 17 | + public static int clampInt(int number, int minimum, int maximum) 18 | + { 19 | + return Math.min(Math.max(number, minimum), maximum); 20 | + } 21 | + 22 | + public static long clampLong(long number, long minimum, long maximum) 23 | + { 24 | + return Math.min(Math.max(number, minimum), maximum); 25 | + } 26 | + 27 | + public static double clampDouble(double number, double minimum, double maximum) 28 | + { 29 | + return Math.min(Math.max(number, minimum), maximum); 30 | + } 31 | + 32 | + public static int safeDoubleToInt(double number) 33 | + { 34 | + return (int) clampDouble(number, Integer.MIN_VALUE, Integer.MAX_VALUE); 35 | + } 36 | + 37 | + public static int safeLongToInt(long number) 38 | + { 39 | + return (int) clampLong(number, Integer.MIN_VALUE, Integer.MAX_VALUE); 40 | + } 41 | +} 42 | diff --git a/src/main/java/me/totalfreedom/scissors/NbtUtility.java b/src/main/java/me/totalfreedom/scissors/NbtUtility.java 43 | new file mode 100644 44 | index 0000000000000000000000000000000000000000..b3efac47ee700d5a7ff26452d6bcbf2f687a32cf 45 | --- /dev/null 46 | +++ b/src/main/java/me/totalfreedom/scissors/NbtUtility.java 47 | @@ -0,0 +1,75 @@ 48 | +package me.totalfreedom.scissors; 49 | + 50 | +import java.nio.charset.StandardCharsets; 51 | +import javax.annotation.Nullable; 52 | +import net.minecraft.nbt.CompoundTag; 53 | +import net.minecraft.nbt.ListTag; 54 | +import net.minecraft.nbt.Tag; 55 | + 56 | +public class NbtUtility 57 | +{ 58 | + public static final long MAXIMUM_SIZE = (256 * 1024); 59 | + 60 | + public static long getTagSize(@Nullable Tag tag, int depth) 61 | + { 62 | + if (depth > 512) 63 | + { 64 | + return 0; 65 | + } 66 | + if (tag == null) 67 | + { 68 | + return 0; 69 | + } 70 | + 71 | + long size = 0; 72 | + 73 | + if (tag.getType() == CompoundTag.TYPE) 74 | + { 75 | + CompoundTag compoundTag = (CompoundTag) tag; 76 | + for (String key : compoundTag.getAllKeys()) 77 | + { 78 | + size += key.getBytes(StandardCharsets.UTF_8).length; 79 | + size += getTagSize(compoundTag.get(key), depth + 1); 80 | + } 81 | + } 82 | + else if (tag.getType() == ListTag.TYPE) 83 | + { 84 | + ListTag listTag = (ListTag) tag; 85 | + for (Tag tag1 : listTag) 86 | + { 87 | + size += getTagSize(tag1, depth + 1); 88 | + } 89 | + } 90 | + else 91 | + { 92 | + size += tag.getAsString().getBytes(StandardCharsets.UTF_8).length; 93 | + } 94 | + 95 | + return size; 96 | + } 97 | + 98 | + public static long getTagSize(@Nullable CompoundTag tag) 99 | + { 100 | + return getTagSize(tag, 0); 101 | + } 102 | + 103 | + public static boolean isTooLarge(@Nullable CompoundTag tag) 104 | + { 105 | + if (tag == null) 106 | + { 107 | + return false; 108 | + } 109 | + return getTagSize(tag) > MAXIMUM_SIZE; 110 | + } 111 | + 112 | + public static class Item 113 | + { 114 | + public static CompoundTag removeItemData(CompoundTag tag) 115 | + { 116 | + CompoundTag cleaned = new CompoundTag(); 117 | + cleaned.putString("id", tag.getString("id")); 118 | + cleaned.putByte("Count", tag.getByte("Count")); 119 | + return cleaned; 120 | + } 121 | + } 122 | +} 123 | diff --git a/src/main/java/me/totalfreedom/scissors/PositionUtility.java b/src/main/java/me/totalfreedom/scissors/PositionUtility.java 124 | new file mode 100644 125 | index 0000000000000000000000000000000000000000..c5dcc833d6f2c0daa1d0c2a7ab81430f25e0b2f3 126 | --- /dev/null 127 | +++ b/src/main/java/me/totalfreedom/scissors/PositionUtility.java 128 | @@ -0,0 +1,53 @@ 129 | +package me.totalfreedom.scissors; 130 | + 131 | +import net.minecraft.core.BlockPos; 132 | +import net.minecraft.world.entity.Entity; 133 | +import net.minecraft.world.level.Level; 134 | +import net.minecraft.world.level.border.WorldBorder; 135 | +import net.minecraft.world.phys.Vec3; 136 | + 137 | +public class PositionUtility 138 | +{ 139 | + 140 | + public static Vec3 getValidVec3FromBlockPos(BlockPos blockPos, Entity entity) 141 | + { 142 | + final BlockPos validBlockPos = getValidBlockPos(blockPos, entity); 143 | + 144 | + return new Vec3(validBlockPos.getX(), validBlockPos.getY(), validBlockPos.getZ()); 145 | + } 146 | + 147 | + public static BlockPos getValidBlockPos(BlockPos blockPos, Entity entity) 148 | + { 149 | + final Level level = entity.level(); 150 | + 151 | + try 152 | + { 153 | + if (level.isInWorldBounds(blockPos)) 154 | + { 155 | + return blockPos; 156 | + } 157 | + else 158 | + { 159 | + final int x = blockPos.getX(); 160 | + final int y = blockPos.getY(); 161 | + final int z = blockPos.getZ(); 162 | + 163 | + final WorldBorder worldBorder = level.getWorldBorder(); 164 | + 165 | + final int maxX = MathUtility.safeDoubleToInt(worldBorder.getMaxX()); 166 | + final int maxY = level.getMaxBuildHeight(); 167 | + final int maxZ = MathUtility.safeDoubleToInt(worldBorder.getMaxZ()); 168 | + 169 | + final int minX = MathUtility.safeDoubleToInt(worldBorder.getMinX()); 170 | + final int minY = level.getMinBuildHeight(); 171 | + final int minZ = MathUtility.safeDoubleToInt(worldBorder.getMinZ()); 172 | + 173 | + return new BlockPos(MathUtility.clampInt(x, minX, maxX), MathUtility.clampInt(y, minY, maxY), MathUtility.clampInt(z, minZ, maxZ)); 174 | + } 175 | + } 176 | + catch (Exception e) 177 | + { // If we throw some sort of exception due to the position being crazy, catch it 178 | + return new BlockPos(0, 0, 0); 179 | + } 180 | + } 181 | +} 182 | -------------------------------------------------------------------------------- /patches/server/0034-Add-configuration-option-to-disable-chat-signatures.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Mon, 15 Apr 2024 23:01:26 -0500 4 | Subject: [PATCH] Add configuration option to disable chat signatures 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java b/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java 8 | index c87b708c368713a23a10ad97704575ee4df27891..4a8ab800d4a974aaf14872d50dcf01c806a0fe3b 100644 9 | --- a/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java 10 | +++ b/src/main/java/net/minecraft/network/chat/OutgoingChatMessage.java 11 | @@ -1,5 +1,6 @@ 12 | package net.minecraft.network.chat; 13 | 14 | +import me.totalfreedom.scissors.ScissorsConfig; 15 | import net.minecraft.server.level.ServerPlayer; 16 | 17 | public interface OutgoingChatMessage { 18 | @@ -46,9 +47,19 @@ public interface OutgoingChatMessage { 19 | // Paper end 20 | PlayerChatMessage playerChatMessage = this.message.filter(filterMaskEnabled); 21 | playerChatMessage = unsigned != null ? playerChatMessage.withUnsignedContent(unsigned) : playerChatMessage; // Paper 22 | - if (!playerChatMessage.isFullyFiltered()) { 23 | + // Sccissors start 24 | + if (!playerChatMessage.isFullyFiltered() && ScissorsConfig.chatSignaturesEnabled) { 25 | sender.connection.sendPlayerChatMessage(playerChatMessage, params); 26 | + return; 27 | } 28 | + sender.connection.sendPlayerChatMessage(new PlayerChatMessage( 29 | + SignedMessageLink.unsigned(playerChatMessage.sender()), 30 | + null, 31 | + SignedMessageBody.unsigned(playerChatMessage.signedContent()), 32 | + unsigned, 33 | + playerChatMessage.filterMask() 34 | + ), params); 35 | + // Scissors end 36 | } 37 | } 38 | } 39 | diff --git a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java 40 | index 0af9ed92824ccf30814eceb6a2c2e5c12661c991..c92374104b4aed2f952b250c5559ab9cc83532da 100644 41 | --- a/src/main/java/net/minecraft/network/chat/SignedMessageChain.java 42 | +++ b/src/main/java/net/minecraft/network/chat/SignedMessageChain.java 43 | @@ -5,6 +5,8 @@ import java.time.Instant; 44 | import java.util.UUID; 45 | import java.util.function.BooleanSupplier; 46 | import javax.annotation.Nullable; 47 | + 48 | +import me.totalfreedom.scissors.ScissorsConfig; 49 | import net.minecraft.util.SignatureValidator; 50 | import net.minecraft.util.Signer; 51 | import net.minecraft.world.entity.player.ProfilePublicKey; 52 | @@ -45,7 +47,7 @@ public class SignedMessageChain { 53 | if (!playerChatMessage.verify(signatureValidator)) { 54 | throw new SignedMessageChain.DecodeException(Component.translatable("multiplayer.disconnect.unsigned_chat"), true, org.bukkit.event.player.PlayerKickEvent.Cause.UNSIGNED_CHAT); // Paper - kick event causes 55 | } else { 56 | - if (playerChatMessage.hasExpiredServer(Instant.now())) { 57 | + if (playerChatMessage.hasExpiredServer(Instant.now()) && ScissorsConfig.chatSignaturesEnabled) { // Scissors 58 | LOGGER.warn("Received expired chat: '{}'. Is the client/server system time unsynchronized?", body.content()); 59 | } 60 | 61 | diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 62 | index 80f0f88258770862f419e4faba4cfca4c0457b2c..c0aa9520d547d6d77169fd1dbb02844b90ef4a1d 100644 63 | --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 64 | +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java 65 | @@ -1,5 +1,6 @@ 66 | package net.minecraft.server.network; 67 | 68 | +import me.totalfreedom.scissors.ScissorsConfig; 69 | import me.totalfreedom.scissors.event.player.SpectatorTeleportEvent; // Scissors 70 | import com.google.common.collect.Lists; 71 | import com.google.common.primitives.Floats; 72 | @@ -2243,7 +2244,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 73 | 74 | private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) { 75 | ServerGamePacketListenerImpl.LOGGER.warn("Failed to update secure chat state for {}: '{}'", this.player.getGameProfile().getName(), exception.getComponent().getString()); 76 | - if (exception.shouldDisconnect()) { 77 | + if (exception.shouldDisconnect() && ScissorsConfig.chatSignaturesEnabled) { // Scissors - Do not kick when chat signatures are disabled 78 | this.disconnect(exception.getComponent(), exception.kickCause); // Paper - kick event causes 79 | } else { 80 | this.player.sendSystemMessage(exception.getComponent().copy().withStyle(ChatFormatting.RED)); 81 | @@ -2291,6 +2292,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 82 | Optional optional = this.lastSeenMessages.applyUpdate(acknowledgment); 83 | 84 | if (optional.isEmpty()) { 85 | + if (!ScissorsConfig.chatSignaturesEnabled) return optional; // Scissors 86 | ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); 87 | this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED, org.bukkit.event.player.PlayerKickEvent.Cause.CHAT_VALIDATION_FAILED); // Paper - kick event causes 88 | } 89 | @@ -2489,6 +2491,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 90 | 91 | synchronized (this.lastSeenMessages) { 92 | if (!this.lastSeenMessages.applyOffset(packet.offset())) { 93 | + if (!ScissorsConfig.chatSignaturesEnabled) return; // Scissors 94 | ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString()); 95 | this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED, org.bukkit.event.player.PlayerKickEvent.Cause.CHAT_VALIDATION_FAILED); // Paper - kick event causes 96 | } 97 | @@ -3473,6 +3476,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl 98 | @Override 99 | public void handleChatSessionUpdate(ServerboundChatSessionUpdatePacket packet) { 100 | PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); 101 | + if (!ScissorsConfig.chatSignaturesEnabled) return; // Scissors 102 | RemoteChatSession.Data remotechatsession_a = packet.chatSession(); 103 | ProfilePublicKey.Data profilepublickey_a = this.chatSession != null ? this.chatSession.profilePublicKey().data() : null; 104 | ProfilePublicKey.Data profilepublickey_a1 = remotechatsession_a.profilePublicKey(); 105 | -------------------------------------------------------------------------------- /patches/server/0004-ResourceLocation-validation.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Video 3 | Date: Wed, 24 Jan 2024 16:28:16 -0600 4 | Subject: [PATCH] ResourceLocation validation 5 | 6 | 7 | diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java 8 | index 15173e715fa36546820d930a46e0f0c493d07cfc..356cc6f468975faa676db87db8fc0fa2df32f020 100644 9 | --- a/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java 10 | +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperContainerEntityLootableInventory.java 11 | @@ -17,7 +17,7 @@ public class PaperContainerEntityLootableInventory implements PaperLootableEntit 12 | 13 | @Override 14 | public org.bukkit.loot.LootTable getLootTable() { 15 | - return entity.getLootTable() != null && !entity.getLootTable().getPath().isEmpty() ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.getLootTable())) : null; 16 | + return entity.getLootTable() != null && !entity.getLootTable().getPath().isEmpty() && entity.getLootTable().toString().length() < 256 ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.getLootTable())) : null; // Scissors - Validate length of loot tables before even trying 17 | } 18 | 19 | @Override 20 | diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java 21 | index 2ee4ee14ab3345486dad6b24fd9a4fcc6c746b99..c5ac6cda91a81d3075f5c763e30dc009b6be7936 100644 22 | --- a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java 23 | +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java 24 | @@ -15,7 +15,7 @@ public class PaperTileEntityLootableInventory implements PaperLootableBlockInven 25 | 26 | @Override 27 | public org.bukkit.loot.LootTable getLootTable() { 28 | - return tileEntityLootable.lootTable != null && !tileEntityLootable.lootTable.getPath().isEmpty() ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; 29 | + return tileEntityLootable.lootTable != null && !tileEntityLootable.lootTable.getPath().isEmpty() && tileEntityLootable.lootTable.toString().length() < 256 ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; // Scissors - Validate length of loot tables before even trying 30 | } 31 | 32 | @Override 33 | diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java 34 | index 094ab43e5a209ea848bf0994db9018281c64e08d..c6faba7da6809e24d734b7d6b0b787d20163b051 100644 35 | --- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java 36 | +++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java 37 | @@ -410,7 +410,7 @@ public class AreaEffectCloud extends Entity implements TraceableEntity { 38 | try { 39 | this.setParticle(ParticleArgument.readParticle(new StringReader(nbt.getString("Particle")), (HolderLookup) BuiltInRegistries.PARTICLE_TYPE.asLookup())); 40 | } catch (CommandSyntaxException commandsyntaxexception) { 41 | - AreaEffectCloud.LOGGER.warn("Couldn't load custom particle {}", nbt.getString("Particle"), commandsyntaxexception); 42 | + // Scissors - Don't log custom particle errors 43 | } 44 | } 45 | 46 | diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java 47 | index 09e8445a3f8c6b3ebc852a75a9a25b41a51ba659..cfb2ce684da0ae97a844554b5ad3d41290058f32 100644 48 | --- a/src/main/java/net/minecraft/world/entity/EntityType.java 49 | +++ b/src/main/java/net/minecraft/world/entity/EntityType.java 50 | @@ -595,7 +595,7 @@ public class EntityType implements FeatureElement, EntityTypeT 51 | if (generation) entity.generation = true; // Paper - Don't fire sync event during generation 52 | entity.load(nbt); 53 | }, () -> { 54 | - EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id")); 55 | + // Scissors - Don't log invalid entities 56 | }); 57 | } 58 | 59 | diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java 60 | index f6942cb3ef1f9ef03708d4bc932ea9aeb1c13894..8b32864bafb3c1948993688be8f639dd6492057e 100644 61 | --- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java 62 | +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java 63 | @@ -34,8 +34,14 @@ public abstract class CraftLootable 64 | return null; 65 | } 66 | 67 | - ResourceLocation key = this.getSnapshot().lootTable; 68 | - return Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(key)); 69 | + // Scissors start - Return a null loot table if the specified loot table is not valid 70 | + try { 71 | + ResourceLocation key = this.getSnapshot().lootTable; 72 | + return Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(key)); 73 | + } catch (Exception ex) { 74 | + return null; 75 | + } 76 | + // Scissors end 77 | } 78 | 79 | @Override 80 | diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java 81 | index 313ee5c8737b2e57f9b5db6512c1871766b2ccd4..a115a13ec911884a804800fc13f0347be1a30932 100644 82 | --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java 83 | +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java 84 | @@ -33,8 +33,15 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo 85 | return null; // return empty loot table? 86 | } 87 | 88 | - NamespacedKey key = CraftNamespacedKey.fromMinecraft(nmsTable); 89 | - return Bukkit.getLootTable(key); 90 | + // Scissors start - Return a null loot table if the specified loot table is not valid 91 | + try 92 | + { 93 | + NamespacedKey key = CraftNamespacedKey.fromMinecraft(nmsTable); 94 | + return Bukkit.getLootTable(key); 95 | + } catch (Exception exception) { 96 | + return null; 97 | + } 98 | + // Scissors end 99 | } 100 | 101 | @Override 102 | diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java 103 | index 31f62fbb54ec7b270fbd8afba7bd7c4bfafa09e3..684e69753be0398ebe57172454aba8cc45cf6502 100644 104 | --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java 105 | +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java 106 | @@ -80,8 +80,15 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { 107 | 108 | @Override 109 | public LootTable getLootTable() { 110 | - NamespacedKey key = CraftNamespacedKey.fromMinecraft(this.getHandle().getLootTable()); 111 | - return Bukkit.getLootTable(key); 112 | + // Scissors start - Return a null loot table if the specified loot table is not valid 113 | + try 114 | + { 115 | + NamespacedKey key = CraftNamespacedKey.fromMinecraft(this.getHandle().getLootTable()); 116 | + return Bukkit.getLootTable(key); 117 | + } catch (Exception ex) { 118 | + return null; 119 | + } 120 | + // Scissors end 121 | } 122 | 123 | @Override 124 | -------------------------------------------------------------------------------- /patches/server/0001-Build-changes.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Sun, 10 Dec 2023 12:34:45 -0600 4 | Subject: [PATCH] Build changes 5 | 6 | 7 | diff --git a/build.gradle.kts b/build.gradle.kts 8 | index bcfe59b6efb628ee1e7f9d60667360d4d885fb6a..855784d7f9c2993c5d91f67c9b8cc46fe6e4147e 100644 9 | --- a/build.gradle.kts 10 | +++ b/build.gradle.kts 11 | @@ -13,8 +13,12 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { 12 | val alsoShade: Configuration by configurations.creating 13 | 14 | dependencies { 15 | - implementation(project(":paper-api")) 16 | - implementation(project(":paper-mojangapi")) 17 | + // Scissors start 18 | + implementation(project(":Scissors-API")) 19 | + implementation("io.papermc.paper:paper-mojangapi:1.20.4-R0.1-SNAPSHOT") { 20 | + exclude("io.papermc.paper", "paper-api") 21 | + } 22 | + // Scissors end 23 | // Paper start 24 | implementation("org.jline:jline-terminal-jansi:3.21.0") 25 | implementation("net.minecrell:terminalconsoleappender:1.3.0") 26 | @@ -67,11 +71,19 @@ tasks.jar { 27 | val gitHash = git("rev-parse", "--short=7", "HEAD").getText().trim() 28 | val implementationVersion = System.getenv("BUILD_NUMBER") ?: "\"$gitHash\"" 29 | val date = git("show", "-s", "--format=%ci", gitHash).getText().trim() // Paper 30 | - val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper 31 | + // Scissors start 32 | + var gitBranch: String; 33 | + if (System.getenv("JENKINS_URL") == null) 34 | + { 35 | + gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper 36 | + } else { 37 | + gitBranch = System.getenv("GITHUB_BRANCH") 38 | + } 39 | + // Scissors end 40 | attributes( 41 | "Main-Class" to "org.bukkit.craftbukkit.Main", 42 | "Implementation-Title" to "CraftBukkit", 43 | - "Implementation-Version" to "git-Paper-$implementationVersion", 44 | + "Implementation-Version" to "git-Scissors-$implementationVersion", // Scissors 45 | "Implementation-Vendor" to date, // Paper 46 | "Specification-Title" to "Bukkit", 47 | "Specification-Version" to project.version, 48 | @@ -150,7 +162,7 @@ fun TaskContainer.registerRunTask( 49 | name: String, 50 | block: JavaExec.() -> Unit 51 | ): TaskProvider = register(name) { 52 | - group = "paper" 53 | + group = "paperweight" // Scissors 54 | mainClass.set("org.bukkit.craftbukkit.Main") 55 | standardInput = System.`in` 56 | workingDir = rootProject.layout.projectDirectory 57 | diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java 58 | index 4b002e8b75d117b726b0de274a76d3596fce015b..a46d3f40642bbf249c2d24e689f474d07175ca09 100644 59 | --- a/src/main/java/com/destroystokyo/paper/Metrics.java 60 | +++ b/src/main/java/com/destroystokyo/paper/Metrics.java 61 | @@ -593,7 +593,7 @@ public class Metrics { 62 | boolean logFailedRequests = config.getBoolean("logFailedRequests", false); 63 | // Only start Metrics, if it's enabled in the config 64 | if (config.getBoolean("enabled", true)) { 65 | - Metrics metrics = new Metrics("Paper", serverUUID, logFailedRequests, Bukkit.getLogger()); 66 | + Metrics metrics = new Metrics("Scissors", serverUUID, logFailedRequests, Bukkit.getLogger()); // Scissors 67 | 68 | metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { 69 | String minecraftVersion = Bukkit.getVersion(); 70 | @@ -607,11 +607,11 @@ public class Metrics { 71 | final String implVersion = org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion(); 72 | if (implVersion != null) { 73 | final String buildOrHash = implVersion.substring(implVersion.lastIndexOf('-') + 1); 74 | - paperVersion = "git-Paper-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); 75 | + paperVersion = "git-Scissors-%s-%s".formatted(Bukkit.getServer().getMinecraftVersion(), buildOrHash); // Scissors 76 | } else { 77 | paperVersion = "unknown"; 78 | } 79 | - metrics.addCustomChart(new Metrics.SimplePie("paper_version", () -> paperVersion)); 80 | + metrics.addCustomChart(new Metrics.SimplePie("scissors_version", () -> paperVersion)); // Scissors 81 | 82 | metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { 83 | Map> map = new HashMap<>(); 84 | diff --git a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java 85 | index c5d5648f4ca603ef2b1df723b58f9caf4dd3c722..21ded7c14c56a40feaa7741131be5166947f7169 100644 86 | --- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java 87 | +++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java 88 | @@ -17,7 +17,7 @@ public final class PaperConsole extends SimpleTerminalConsole { 89 | @Override 90 | protected LineReader buildReader(LineReaderBuilder builder) { 91 | builder 92 | - .appName("Paper") 93 | + .appName("Scissors") // Scissors 94 | .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) 95 | .completer(new ConsoleCommandCompleter(this.server)) 96 | .option(LineReader.Option.COMPLETE_IN_WORD, true); 97 | diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java 98 | index c8772c773f9933ed1d1debfe707af4373c458152..05b0d82114aadbb713b7e5dad94ee0fe6221856a 100644 99 | --- a/src/main/java/net/minecraft/server/MinecraftServer.java 100 | +++ b/src/main/java/net/minecraft/server/MinecraftServer.java 101 | @@ -1865,7 +1865,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Paper 120 | private final String serverVersion; 121 | private final String bukkitVersion = Versioning.getBukkitVersion(); 122 | private final Logger logger = Logger.getLogger("Minecraft"); 123 | diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java 124 | index 774556a62eb240da42e84db4502e2ed43495be17..741c76c4dfa0bb34cc23bd795c194bdea10418cc 100644 125 | --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java 126 | +++ b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java 127 | @@ -11,7 +11,7 @@ public final class Versioning { 128 | public static String getBukkitVersion() { 129 | String result = "Unknown-Version"; 130 | 131 | - InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/io.papermc.paper/paper-api/pom.properties"); 132 | + InputStream stream = Bukkit.class.getClassLoader().getResourceAsStream("META-INF/maven/me.totalfreedom.scissors/Scissors-API/pom.properties"); // Scissors 133 | Properties properties = new Properties(); 134 | 135 | if (stream != null) { 136 | -------------------------------------------------------------------------------- /patches/server/0015-Limit-string-tag-visitors-to-1024-elements.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Luna 3 | Date: Fri, 8 Apr 2022 23:38:12 -0300 4 | Subject: [PATCH] Limit string tag visitors to 1024 elements 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/nbt/SnbtPrinterTagVisitor.java b/src/main/java/net/minecraft/nbt/SnbtPrinterTagVisitor.java 8 | index b45bb4ddf6b586ba1285db230e0bc3d1b5e447e8..4a46935cac263325a87a1b0bf32302839a75516e 100644 9 | --- a/src/main/java/net/minecraft/nbt/SnbtPrinterTagVisitor.java 10 | +++ b/src/main/java/net/minecraft/nbt/SnbtPrinterTagVisitor.java 11 | @@ -89,6 +89,7 @@ public class SnbtPrinterTagVisitor implements TagVisitor { 12 | public void visitByteArray(ByteArrayTag element) { 13 | StringBuilder stringBuilder = new StringBuilder("[").append("B").append(";"); 14 | byte[] bs = element.getAsByteArray(); 15 | + if (bs.length > 1024) { this.result = stringBuilder.append("]").toString(); return; } // Scissors 16 | 17 | for (int i = 0; i < bs.length; i++) { 18 | stringBuilder.append(" ").append(bs[i]).append("B"); 19 | @@ -105,6 +106,7 @@ public class SnbtPrinterTagVisitor implements TagVisitor { 20 | public void visitIntArray(IntArrayTag element) { 21 | StringBuilder stringBuilder = new StringBuilder("[").append("I").append(";"); 22 | int[] is = element.getAsIntArray(); 23 | + if (is.length > 1024) { this.result = stringBuilder.append("]").toString(); return; } // Scissors 24 | 25 | for (int i = 0; i < is.length; i++) { 26 | stringBuilder.append(" ").append(is[i]); 27 | @@ -122,6 +124,7 @@ public class SnbtPrinterTagVisitor implements TagVisitor { 28 | String string = "L"; 29 | StringBuilder stringBuilder = new StringBuilder("[").append("L").append(";"); 30 | long[] ls = element.getAsLongArray(); 31 | + if (ls.length > 1024) { this.result = stringBuilder.append("]").toString(); return; } // Scissors 32 | 33 | for (int i = 0; i < ls.length; i++) { 34 | stringBuilder.append(" ").append(ls[i]).append("L"); 35 | @@ -136,7 +139,7 @@ public class SnbtPrinterTagVisitor implements TagVisitor { 36 | 37 | @Override 38 | public void visitList(ListTag element) { 39 | - if (element.isEmpty()) { 40 | + if (element.isEmpty() || element.size() > 1024) { // Scissors 41 | this.result = "[]"; 42 | } else { 43 | StringBuilder stringBuilder = new StringBuilder("["); 44 | @@ -166,7 +169,7 @@ public class SnbtPrinterTagVisitor implements TagVisitor { 45 | 46 | @Override 47 | public void visitCompound(CompoundTag compound) { 48 | - if (compound.isEmpty()) { 49 | + if (compound.isEmpty() || compound.size() > 1024) { // Scissors 50 | this.result = "{}"; 51 | } else { 52 | StringBuilder stringBuilder = new StringBuilder("{"); 53 | diff --git a/src/main/java/net/minecraft/nbt/StringTagVisitor.java b/src/main/java/net/minecraft/nbt/StringTagVisitor.java 54 | index d8892641d5671fa100aeb43d42ebb6103a2d280c..d10242ecd6f8442e1af3f4cd13f769517b33058a 100644 55 | --- a/src/main/java/net/minecraft/nbt/StringTagVisitor.java 56 | +++ b/src/main/java/net/minecraft/nbt/StringTagVisitor.java 57 | @@ -53,6 +53,7 @@ public class StringTagVisitor implements TagVisitor { 58 | public void visitByteArray(ByteArrayTag element) { 59 | this.builder.append("[B;"); 60 | byte[] bs = element.getAsByteArray(); 61 | + if (bs.length > 1024) { this.builder.append(']'); return; } // Scissors 62 | 63 | for (int i = 0; i < bs.length; i++) { 64 | if (i != 0) { 65 | @@ -69,6 +70,7 @@ public class StringTagVisitor implements TagVisitor { 66 | public void visitIntArray(IntArrayTag element) { 67 | this.builder.append("[I;"); 68 | int[] is = element.getAsIntArray(); 69 | + if (is.length > 1024) { this.builder.append(']'); return; } // Scissors 70 | 71 | for (int i = 0; i < is.length; i++) { 72 | if (i != 0) { 73 | @@ -85,6 +87,7 @@ public class StringTagVisitor implements TagVisitor { 74 | public void visitLongArray(LongArrayTag element) { 75 | this.builder.append("[L;"); 76 | long[] ls = element.getAsLongArray(); 77 | + if (ls.length > 1024) { this.builder.append(']'); return; } // Scissors 78 | 79 | for (int i = 0; i < ls.length; i++) { 80 | if (i != 0) { 81 | @@ -100,6 +103,7 @@ public class StringTagVisitor implements TagVisitor { 82 | @Override 83 | public void visitList(ListTag element) { 84 | this.builder.append('['); 85 | + if (element.size() > 1024) { this.builder.append(']'); return; } // Scissors 86 | 87 | for (int i = 0; i < element.size(); i++) { 88 | if (i != 0) { 89 | @@ -116,6 +120,7 @@ public class StringTagVisitor implements TagVisitor { 90 | public void visitCompound(CompoundTag compound) { 91 | this.builder.append('{'); 92 | List list = Lists.newArrayList(compound.getAllKeys()); 93 | + if (list.size() > 1024) { this.builder.append('}'); return; } // Scissors 94 | Collections.sort(list); 95 | 96 | for (String string : list) { 97 | diff --git a/src/main/java/net/minecraft/nbt/TextComponentTagVisitor.java b/src/main/java/net/minecraft/nbt/TextComponentTagVisitor.java 98 | index 4e238ae29347c5e976ff0d506e94972df0aa7362..9776b9741a7ec46c603b2c2bccd5f006c15cee41 100644 99 | --- a/src/main/java/net/minecraft/nbt/TextComponentTagVisitor.java 100 | +++ b/src/main/java/net/minecraft/nbt/TextComponentTagVisitor.java 101 | @@ -97,6 +97,7 @@ public class TextComponentTagVisitor implements TagVisitor { 102 | Component component = Component.literal("B").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE); 103 | MutableComponent mutableComponent = Component.literal("[").append(component).append(";"); 104 | byte[] bs = element.getAsByteArray(); 105 | + if (bs.length > 1024) { this.result = mutableComponent.append("]"); return; } // Scissors 106 | 107 | for (int i = 0; i < bs.length; i++) { 108 | MutableComponent mutableComponent2 = Component.literal(String.valueOf(bs[i])).withStyle(SYNTAX_HIGHLIGHTING_NUMBER); 109 | @@ -115,6 +116,7 @@ public class TextComponentTagVisitor implements TagVisitor { 110 | Component component = Component.literal("I").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE); 111 | MutableComponent mutableComponent = Component.literal("[").append(component).append(";"); 112 | int[] is = element.getAsIntArray(); 113 | + if (is.length > 1024) { this.result = mutableComponent.append("]"); return; } // Scissors 114 | 115 | for (int i = 0; i < is.length; i++) { 116 | mutableComponent.append(" ").append(Component.literal(String.valueOf(is[i])).withStyle(SYNTAX_HIGHLIGHTING_NUMBER)); 117 | @@ -132,6 +134,7 @@ public class TextComponentTagVisitor implements TagVisitor { 118 | Component component = Component.literal("L").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE); 119 | MutableComponent mutableComponent = Component.literal("[").append(component).append(";"); 120 | long[] ls = element.getAsLongArray(); 121 | + if (ls.length > 1024) { this.result = mutableComponent.append("]"); return; } // Scissors 122 | 123 | for (int i = 0; i < ls.length; i++) { 124 | Component component2 = Component.literal(String.valueOf(ls[i])).withStyle(SYNTAX_HIGHLIGHTING_NUMBER); 125 | @@ -147,7 +150,7 @@ public class TextComponentTagVisitor implements TagVisitor { 126 | 127 | @Override 128 | public void visitList(ListTag element) { 129 | - if (element.isEmpty()) { 130 | + if (element.isEmpty() || element.size() > 1024) { // Scissors 131 | this.result = Component.literal("[]"); 132 | } else if (INLINE_ELEMENT_TYPES.contains(element.getElementType()) && element.size() <= 8) { 133 | String string = ELEMENT_SEPARATOR + " "; 134 | @@ -190,7 +193,7 @@ public class TextComponentTagVisitor implements TagVisitor { 135 | 136 | @Override 137 | public void visitCompound(CompoundTag compound) { 138 | - if (compound.isEmpty()) { 139 | + if (compound.isEmpty() || compound.size() > 1024) { // Scissors 140 | this.result = Component.literal("{}"); 141 | } else { 142 | MutableComponent mutableComponent = Component.literal("{"); 143 | -------------------------------------------------------------------------------- /patches/server/0022-Add-MasterBlockFireEvent.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Allink 3 | Date: Sun, 10 Dec 2023 18:11:55 -0600 4 | Subject: [PATCH] Add MasterBlockFireEvent 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/level/block/CommandBlock.java b/src/main/java/net/minecraft/world/level/block/CommandBlock.java 8 | index 7ef14e4441a329c680a5dfe4bfb5033ffcb8f9d5..eff5bdf00b0aa7a9925ff59a62ead72509dc67b8 100644 9 | --- a/src/main/java/net/minecraft/world/level/block/CommandBlock.java 10 | +++ b/src/main/java/net/minecraft/world/level/block/CommandBlock.java 11 | @@ -4,6 +4,7 @@ import com.mojang.logging.LogUtils; 12 | import com.mojang.serialization.Codec; 13 | import com.mojang.serialization.MapCodec; 14 | import com.mojang.serialization.codecs.RecordCodecBuilder; 15 | +import me.totalfreedom.scissors.event.block.MasterBlockFireEvent; 16 | import net.minecraft.core.BlockPos; 17 | import net.minecraft.core.Direction; 18 | import net.minecraft.server.level.ServerLevel; 19 | @@ -28,6 +29,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties; 20 | import net.minecraft.world.level.block.state.properties.BooleanProperty; 21 | import net.minecraft.world.level.block.state.properties.DirectionProperty; 22 | import net.minecraft.world.phys.BlockHitResult; 23 | +import org.bukkit.Location; 24 | import org.slf4j.Logger; 25 | 26 | import org.bukkit.event.block.BlockRedstoneEvent; // CraftBukkit 27 | @@ -130,6 +132,14 @@ public class CommandBlock extends BaseEntityBlock implements GameMasterBlock { 28 | } 29 | 30 | private void execute(BlockState state, Level world, BlockPos pos, BaseCommandBlock executor, boolean hasCommand) { 31 | + // Scissors start - Add master block fire event 32 | + final MasterBlockFireEvent event = new MasterBlockFireEvent(new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ())); 33 | + if (!event.callEvent()) 34 | + { 35 | + return; 36 | + } 37 | + // Scissors end 38 | + 39 | if (hasCommand) { 40 | executor.performCommand(world); 41 | } else { 42 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java 43 | index 447b0359922011fe12b1bb9628d23a47c9d7dc89..0d6be671e1512074ae1265fe93a5d5437f3929dd 100644 44 | --- a/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java 45 | +++ b/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java 46 | @@ -2,6 +2,8 @@ package net.minecraft.world.level.block.entity; 47 | 48 | import java.util.Arrays; 49 | import java.util.Optional; 50 | + 51 | +import me.totalfreedom.scissors.event.block.MasterBlockFireEvent; 52 | import net.minecraft.core.BlockPos; 53 | import net.minecraft.core.Holder; 54 | import net.minecraft.core.Registry; 55 | @@ -17,6 +19,7 @@ import net.minecraft.world.level.block.JigsawBlock; 56 | import net.minecraft.world.level.block.state.BlockState; 57 | import net.minecraft.world.level.levelgen.structure.pools.JigsawPlacement; 58 | import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool; 59 | +import org.bukkit.Location; 60 | 61 | public class JigsawBlockEntity extends BlockEntity { 62 | public static final String TARGET = "target"; 63 | @@ -134,6 +137,16 @@ public class JigsawBlockEntity extends BlockEntity { 64 | } 65 | 66 | public void generate(ServerLevel world, int maxDepth, boolean keepJigsaws) { 67 | + // Scissors start - Add master block fire event 68 | + final BlockPos pos = this.getBlockPos(); 69 | + final MasterBlockFireEvent event = new MasterBlockFireEvent(new Location(this.getLevel().getWorld(), pos.getX(), pos.getY(), pos.getZ())); 70 | + 71 | + if (!event.callEvent()) 72 | + { 73 | + return; 74 | + } 75 | + // Scissors end 76 | + 77 | BlockPos blockPos = this.getBlockPos().relative(this.getBlockState().getValue(JigsawBlock.ORIENTATION).front()); 78 | Registry registry = world.registryAccess().registryOrThrow(Registries.TEMPLATE_POOL); 79 | // Paper start - Replace getHolderOrThrow with a null check 80 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/StructureBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/StructureBlockEntity.java 81 | index 29c59e4a1283ac211b18b953ed6c03834a2587bd..fb385cd66226200ed0b8439cb6659dbac6c2b229 100644 82 | --- a/src/main/java/net/minecraft/world/level/block/entity/StructureBlockEntity.java 83 | +++ b/src/main/java/net/minecraft/world/level/block/entity/StructureBlockEntity.java 84 | @@ -5,6 +5,8 @@ import java.util.Objects; 85 | import java.util.Optional; 86 | import java.util.stream.Stream; 87 | import javax.annotation.Nullable; 88 | + 89 | +import me.totalfreedom.scissors.event.block.MasterBlockFireEvent; 90 | import net.minecraft.ResourceLocationException; 91 | import net.minecraft.Util; 92 | import net.minecraft.core.BlockPos; 93 | @@ -29,6 +31,7 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.BlockRotProce 94 | import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; 95 | import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; 96 | import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; 97 | +import org.bukkit.Location; 98 | 99 | public class StructureBlockEntity extends BlockEntity { 100 | private static final int SCAN_CORNER_BLOCKS_RANGE = 5; 101 | @@ -259,7 +262,7 @@ public class StructureBlockEntity extends BlockEntity { 102 | return false; 103 | } else { 104 | BlockPos blockPos = this.getBlockPos(); 105 | - int i = 80; 106 | + // Scissors - Obfuscation fixes 107 | BlockPos blockPos2 = new BlockPos(blockPos.getX() - 80, this.level.getMinBuildHeight(), blockPos.getZ() - 80); 108 | BlockPos blockPos3 = new BlockPos(blockPos.getX() + 80, this.level.getMaxBuildHeight() - 1, blockPos.getZ() + 80); 109 | Stream stream = this.getRelatedCorners(blockPos2, blockPos3); 110 | @@ -316,6 +319,16 @@ public class StructureBlockEntity extends BlockEntity { 111 | if (this.structureName == null) { 112 | return false; 113 | } else { 114 | + // Scissors start - Add master block fire event 115 | + final BlockPos pos = this.getBlockPos(); 116 | + final MasterBlockFireEvent event = new MasterBlockFireEvent(new Location(this.getLevel().getWorld(), pos.getX(), pos.getY(), pos.getZ())); 117 | + 118 | + if (!event.callEvent()) 119 | + { 120 | + return false; 121 | + } 122 | + // Scissors end 123 | + 124 | BlockPos blockPos = this.getBlockPos().offset(this.structurePos); 125 | ServerLevel serverLevel = (ServerLevel)this.level; 126 | StructureTemplateManager structureTemplateManager = serverLevel.getStructureManager(); 127 | @@ -367,6 +380,16 @@ public class StructureBlockEntity extends BlockEntity { 128 | if (structureTemplate == null) { 129 | return false; 130 | } else { 131 | + // Scissors start - Add master block fire event 132 | + final BlockPos blockPos = this.getBlockPos(); 133 | + final MasterBlockFireEvent event = new MasterBlockFireEvent(new Location(this.getLevel().getWorld(), blockPos.getX(), blockPos.getY(), blockPos.getZ())); 134 | + 135 | + if (!event.callEvent()) 136 | + { 137 | + return false; 138 | + } 139 | + // Scissors end 140 | + 141 | this.loadStructureInfo(structureTemplate); 142 | return true; 143 | } 144 | @@ -407,6 +430,15 @@ public class StructureBlockEntity extends BlockEntity { 145 | } 146 | 147 | public void unloadStructure() { 148 | + // Scissors start - Add master block fire event 149 | + final BlockPos blockPos = this.getBlockPos(); 150 | + final MasterBlockFireEvent event = new MasterBlockFireEvent(new Location(this.getLevel().getWorld(), blockPos.getX(), blockPos.getY(), blockPos.getZ())); 151 | + 152 | + if (!event.callEvent()) 153 | + { 154 | + return; 155 | + } 156 | + // Scissors end 157 | if (this.structureName != null) { 158 | ServerLevel serverLevel = (ServerLevel)this.level; 159 | StructureTemplateManager structureTemplateManager = serverLevel.getStructureManager(); 160 | -------------------------------------------------------------------------------- /patches/server/0012-Better-handling-of-invalid-JSON-components.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Mon, 15 Apr 2024 22:36:13 -0500 4 | Subject: [PATCH] Better handling of invalid JSON components 5 | 6 | 7 | diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java 8 | index e028353e0261310afc42ca0454b723d9f1ffc131..ed8810319db2ce754245193a62ea7a9a32ac13ec 100644 9 | --- a/src/main/java/io/papermc/paper/util/MCUtil.java 10 | +++ b/src/main/java/io/papermc/paper/util/MCUtil.java 11 | @@ -675,12 +675,6 @@ public final class MCUtil { 12 | return null; 13 | } 14 | String string = compound.getString(key); 15 | - try { 16 | - return net.minecraft.network.chat.Component.Serializer.fromJson(string); 17 | - } catch (com.google.gson.JsonParseException e) { 18 | - org.bukkit.Bukkit.getLogger().warning("Unable to parse " + key + " from " + compound +": " + e.getMessage()); 19 | - } 20 | - 21 | - return null; 22 | + return net.minecraft.network.chat.Component.Serializer.fromJsonSafe(string); // Scissors 23 | } 24 | } 25 | diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java 26 | index d3a80d0a23be762c05931ae8001d98e43cab2b4a..ae84d06564b2560e13404f6d89f88ad71dbc2cc6 100644 27 | --- a/src/main/java/net/minecraft/network/chat/Component.java 28 | +++ b/src/main/java/net/minecraft/network/chat/Component.java 29 | @@ -315,6 +315,26 @@ public interface Component extends Message, FormattedText, Iterable { 30 | return json == null ? null : Serializer.deserialize(json); 31 | } 32 | 33 | + // Scissors start 34 | + @Nullable 35 | + public static MutableComponent fromJsonSafe(String json) { 36 | + try { 37 | + return fromJson(json); 38 | + } catch (Exception ex) { 39 | + return Component.empty().append("** Invalid JSON Component **").withStyle(ChatFormatting.RED); 40 | + } 41 | + } 42 | + 43 | + @Nullable 44 | + public static MutableComponent fromJsonSafe(JsonElement json) { 45 | + try { 46 | + return fromJson(json); 47 | + } catch (Exception ex) { 48 | + return Component.empty().append("** Invalid JSON Component **").withStyle(ChatFormatting.RED); 49 | + } 50 | + } 51 | + // Scissors end 52 | + 53 | @Nullable 54 | public static MutableComponent fromJsonLenient(String json) { 55 | JsonReader jsonreader = new JsonReader(new StringReader(json)); 56 | diff --git a/src/main/java/net/minecraft/network/chat/HoverEvent.java b/src/main/java/net/minecraft/network/chat/HoverEvent.java 57 | index a82b4e39c3160114aded3f33c85fad2e95065b72..e1f15ac481ab598e420ad79bcf289251d9f1c99a 100644 58 | --- a/src/main/java/net/minecraft/network/chat/HoverEvent.java 59 | +++ b/src/main/java/net/minecraft/network/chat/HoverEvent.java 60 | @@ -147,7 +147,7 @@ public class HoverEvent { 61 | public static DataResult legacyCreate(Component text) { 62 | try { 63 | CompoundTag compoundTag = TagParser.parseTag(text.getString()); 64 | - Component component = Component.Serializer.fromJson(compoundTag.getString("name")); 65 | + Component component = Component.Serializer.fromJsonSafe(compoundTag.getString("name")); // Scissors - Use safer method for getting Components from JSON 66 | EntityType entityType = BuiltInRegistries.ENTITY_TYPE.get(new ResourceLocation(compoundTag.getString("type"))); 67 | // Scissors start 68 | UUID uUID; 69 | diff --git a/src/main/java/net/minecraft/network/chat/contents/NbtContents.java b/src/main/java/net/minecraft/network/chat/contents/NbtContents.java 70 | index c5673657ca6332147a5cbd2f4107fee13b9b7f47..3fec6f3e0adef6e2094157ef9040c7c6dc41a6c2 100644 71 | --- a/src/main/java/net/minecraft/network/chat/contents/NbtContents.java 72 | +++ b/src/main/java/net/minecraft/network/chat/contents/NbtContents.java 73 | @@ -124,10 +124,10 @@ public class NbtContents implements ComponentContents { 74 | ); 75 | return stream.flatMap(text -> { 76 | try { 77 | - MutableComponent mutableComponent = Component.Serializer.fromJson(text); 78 | + MutableComponent mutableComponent = Component.Serializer.fromJsonSafe(text); // Scissors 79 | return Stream.of(ComponentUtils.updateForEntity(source, mutableComponent, sender, depth)); 80 | } catch (Exception var5x) { 81 | - LOGGER.warn("Failed to parse component: {}", text, var5x); 82 | + // Scissors - don't log 83 | return Stream.of(); 84 | } 85 | }).reduce((accumulator, current) -> accumulator.append(component).append(current)).orElseGet(Component::empty); 86 | diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java 87 | index 637478fd8a284e6833cf8f5fa17ccf9d73d1dd3f..2ecf2d8ff546ed097cb3b547db22d28a31d29ec4 100644 88 | --- a/src/main/java/net/minecraft/world/entity/Entity.java 89 | +++ b/src/main/java/net/minecraft/world/entity/Entity.java 90 | @@ -2545,11 +2545,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S 91 | if (nbt.contains("CustomName", 8)) { 92 | String s = nbt.getString("CustomName"); 93 | 94 | - try { 95 | - this.setCustomName(Component.Serializer.fromJson(s)); 96 | - } catch (Exception exception) { 97 | - Entity.LOGGER.warn("Failed to parse entity custom name {}", s, exception); 98 | - } 99 | + this.setCustomName(Component.Serializer.fromJsonSafe(s)); // Scissors - Use safer method for getting Components from JSON 100 | } 101 | 102 | this.setCustomNameVisible(nbt.getBoolean("CustomNameVisible")); 103 | diff --git a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java 104 | index 7eb1c28886741bdfe7985d16b6824f3e85ffae50..a6b7ff2e50c9700589428cc7d61b5ef9f9082ea8 100644 105 | --- a/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java 106 | +++ b/src/main/java/net/minecraft/world/scores/ScoreboardSaveData.java 107 | @@ -41,7 +41,7 @@ public class ScoreboardSaveData extends SavedData { 108 | CompoundTag compoundTag = nbt.getCompound(i); 109 | String string = compoundTag.getString("Name"); 110 | PlayerTeam playerTeam = this.scoreboard.addPlayerTeam(string); 111 | - Component component = Component.Serializer.fromJson(compoundTag.getString("DisplayName")); 112 | + Component component = Component.Serializer.fromJsonSafe(compoundTag.getString("DisplayName")); // Scissors - Use safer method for getting Components from JSON 113 | if (component != null) { 114 | playerTeam.setDisplayName(component); 115 | } 116 | @@ -59,14 +59,14 @@ public class ScoreboardSaveData extends SavedData { 117 | } 118 | 119 | if (compoundTag.contains("MemberNamePrefix", 8)) { 120 | - Component component2 = Component.Serializer.fromJson(compoundTag.getString("MemberNamePrefix")); 121 | + Component component2 = Component.Serializer.fromJsonSafe(compoundTag.getString("MemberNamePrefix")); // Scissors - Use safer method for getting Components from JSON 122 | if (component2 != null) { 123 | playerTeam.setPlayerPrefix(component2); 124 | } 125 | } 126 | 127 | if (compoundTag.contains("MemberNameSuffix", 8)) { 128 | - Component component3 = Component.Serializer.fromJson(compoundTag.getString("MemberNameSuffix")); 129 | + Component component3 = Component.Serializer.fromJsonSafe(compoundTag.getString("MemberNameSuffix")); // Scissors - Use safer method for getting Components from JSON 130 | if (component3 != null) { 131 | playerTeam.setPlayerSuffix(component3); 132 | } 133 | @@ -123,7 +123,7 @@ public class ScoreboardSaveData extends SavedData { 134 | return ObjectiveCriteria.DUMMY; 135 | }); 136 | String string2 = compoundTag.getString("Name"); 137 | - Component component = Component.Serializer.fromJson(compoundTag.getString("DisplayName")); 138 | + Component component = Component.Serializer.fromJsonSafe(compoundTag.getString("DisplayName")); // Scissors - Use safer method for getting Components from JSON 139 | ObjectiveCriteria.RenderType renderType = ObjectiveCriteria.RenderType.byId(compoundTag.getString("RenderType")); 140 | boolean bl = compoundTag.getBoolean("display_auto_update"); 141 | NumberFormat numberFormat = NumberFormatTypes.CODEC.parse(NbtOps.INSTANCE, compoundTag.get("format")).result().orElse(null); 142 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /patches/server/0023-Reset-large-tags.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Telesphoreo 3 | Date: Mon, 15 Apr 2024 22:49:31 -0500 4 | Subject: [PATCH] Reset large tags 5 | 6 | 7 | diff --git a/src/main/java/net/minecraft/world/ContainerHelper.java b/src/main/java/net/minecraft/world/ContainerHelper.java 8 | index 4105bb71b1f1614b3e91478b40b85add94a9257b..52d2a8fd6e16c8d85f2544ffdb9ed4d18b298e1c 100644 9 | --- a/src/main/java/net/minecraft/world/ContainerHelper.java 10 | +++ b/src/main/java/net/minecraft/world/ContainerHelper.java 11 | @@ -2,6 +2,8 @@ package net.minecraft.world; 12 | 13 | import java.util.List; 14 | import java.util.function.Predicate; 15 | + 16 | +import me.totalfreedom.scissors.NbtUtility; // Scissors 17 | import net.minecraft.core.NonNullList; 18 | import net.minecraft.nbt.CompoundTag; 19 | import net.minecraft.nbt.ListTag; 20 | @@ -22,10 +24,12 @@ public class ContainerHelper { 21 | 22 | public static CompoundTag saveAllItems(CompoundTag nbt, NonNullList stacks, boolean setIfEmpty) { 23 | ListTag listTag = new ListTag(); 24 | + long total = 0; // Scissors 25 | 26 | for (int i = 0; i < stacks.size(); i++) { 27 | ItemStack itemStack = stacks.get(i); 28 | if (!itemStack.isEmpty()) { 29 | + total += NbtUtility.getTagSize(itemStack.getTag()); // Scissors 30 | CompoundTag compoundTag = new CompoundTag(); 31 | compoundTag.putByte("Slot", (byte)i); 32 | itemStack.save(compoundTag); 33 | @@ -33,7 +37,7 @@ public class ContainerHelper { 34 | } 35 | } 36 | 37 | - if (!listTag.isEmpty() || setIfEmpty) { 38 | + if ((!listTag.isEmpty() || setIfEmpty) && !(total > NbtUtility.MAXIMUM_SIZE)) { // Scissors 39 | nbt.put("Items", listTag); 40 | } 41 | 42 | @@ -42,11 +46,19 @@ public class ContainerHelper { 43 | 44 | public static void loadAllItems(CompoundTag nbt, NonNullList stacks) { 45 | ListTag listTag = nbt.getList("Items", 10); 46 | + long total = 0; // Scissors - Account for items inside containers 47 | 48 | for (int i = 0; i < listTag.size(); i++) { 49 | CompoundTag compoundTag = listTag.getCompound(i); 50 | int j = compoundTag.getByte("Slot") & 255; 51 | if (j >= 0 && j < stacks.size()) { 52 | + // Scissors start 53 | + total += NbtUtility.getTagSize(compoundTag); 54 | + if (total >= NbtUtility.MAXIMUM_SIZE) { 55 | + stacks.clear(); 56 | + break; 57 | + } 58 | + // Scissors end 59 | stacks.set(j, ItemStack.of(compoundTag)); 60 | } 61 | } 62 | diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java 63 | index 1ad126d992d95062a3db08374db7a927f23a0cac..6af963d383293a4a6f8d517e2dc179ab70744b31 100644 64 | --- a/src/main/java/net/minecraft/world/item/ItemStack.java 65 | +++ b/src/main/java/net/minecraft/world/item/ItemStack.java 66 | @@ -23,6 +23,8 @@ import java.util.function.Predicate; 67 | import java.util.stream.Collectors; 68 | import java.util.stream.Stream; 69 | import javax.annotation.Nullable; 70 | + 71 | +import me.totalfreedom.scissors.NbtUtility; 72 | import net.minecraft.ChatFormatting; 73 | import net.minecraft.Util; 74 | import net.minecraft.advancements.CriteriaTriggers; 75 | @@ -278,6 +280,12 @@ public final class ItemStack { 76 | 77 | // CraftBukkit - break into own method 78 | private void load(CompoundTag nbttagcompound) { 79 | + // Scissors start - Reset large tags 80 | + if (NbtUtility.isTooLarge(nbttagcompound)) { 81 | + // Reset tag without destroying item 82 | + nbttagcompound = NbtUtility.Item.removeItemData(nbttagcompound); 83 | + } 84 | + // Scissors end 85 | this.item = (Item) BuiltInRegistries.ITEM.get(new ResourceLocation(nbttagcompound.getString("id"))); 86 | this.count = nbttagcompound.getByte("Count"); 87 | if (nbttagcompound.contains("tag", 10)) { 88 | @@ -585,7 +593,11 @@ public final class ItemStack { 89 | nbt.putString("id", minecraftkey == null ? "minecraft:air" : minecraftkey.toString()); 90 | nbt.putByte("Count", (byte) this.count); 91 | if (this.tag != null) { 92 | - nbt.put("tag", this.tag.copy()); 93 | + // Scissors start - Don't save large tags 94 | + if (!NbtUtility.isTooLarge(this.tag)) { 95 | + nbt.put("tag", this.tag.copy()); 96 | + } 97 | + // Scissors end 98 | } 99 | 100 | return nbt; 101 | @@ -919,6 +931,7 @@ public final class ItemStack { 102 | // Paper end 103 | 104 | public void setTag(@Nullable CompoundTag nbt) { 105 | + if (NbtUtility.isTooLarge(nbt)) return; // Scissors - Ignore large tags 106 | this.tag = nbt; 107 | this.processEnchantOrder(this.tag); // Paper 108 | if (this.getItem().canBeDepleted()) { 109 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java 110 | index 89d06253b00604114e543ebbe12a9993ae95dc41..d0af3a9b956b37126811080d65474eacd76bc083 100644 111 | --- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java 112 | +++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java 113 | @@ -9,6 +9,8 @@ import java.util.Iterator; 114 | import java.util.List; 115 | import java.util.Map; 116 | import javax.annotation.Nullable; 117 | + 118 | +import me.totalfreedom.scissors.NbtUtility; 119 | import net.minecraft.SharedConstants; 120 | import net.minecraft.Util; 121 | import net.minecraft.core.BlockPos; 122 | @@ -213,6 +215,17 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit 123 | public List transaction = new java.util.ArrayList(); 124 | 125 | public List getContents() { 126 | + // Scissors start - Account for items inside containers 127 | + long total = 0; 128 | + 129 | + for (ItemStack item : this.items) { 130 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 131 | + } 132 | + 133 | + if (total > NbtUtility.MAXIMUM_SIZE) { 134 | + this.items.clear(); 135 | + } 136 | + // Scissors end 137 | return this.items; 138 | } 139 | 140 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java 141 | index 416aa989ebb18a8741cc9d605a1180ab830f6643..af7ed06c083161212784f746290129a17523575a 100644 142 | --- a/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java 143 | +++ b/src/main/java/net/minecraft/world/level/block/entity/BarrelBlockEntity.java 144 | @@ -1,5 +1,6 @@ 145 | package net.minecraft.world.level.block.entity; 146 | 147 | +import me.totalfreedom.scissors.NbtUtility; 148 | import net.minecraft.core.BlockPos; 149 | import net.minecraft.core.Direction; 150 | import net.minecraft.core.NonNullList; 151 | @@ -34,6 +35,17 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { 152 | 153 | @Override 154 | public List getContents() { 155 | + // Scissors start - Account for items inside containers 156 | + long total = 0; 157 | + 158 | + for (ItemStack item : this.items) { 159 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 160 | + } 161 | + 162 | + if (total > NbtUtility.MAXIMUM_SIZE) { 163 | + this.items.clear(); 164 | + } 165 | + // Scissors end 166 | return this.items; 167 | } 168 | 169 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java 170 | index 9bb542ce3a8c52e1688bb1f66fc916dd23a5fd10..d8386aa10dc1616c4da87bc8078548d13bff5bdf 100644 171 | --- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java 172 | +++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java 173 | @@ -3,6 +3,8 @@ package net.minecraft.world.level.block.entity; 174 | import java.util.Arrays; 175 | import java.util.Iterator; 176 | import javax.annotation.Nullable; 177 | + 178 | +import me.totalfreedom.scissors.NbtUtility; 179 | import net.minecraft.core.BlockPos; 180 | import net.minecraft.core.Direction; 181 | import net.minecraft.core.NonNullList; 182 | @@ -73,6 +75,17 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements 183 | } 184 | 185 | public List getContents() { 186 | + // Scissors start - Account for items inside containers 187 | + long total = 0; 188 | + 189 | + for (ItemStack item : this.items) { 190 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 191 | + } 192 | + 193 | + if (total > NbtUtility.MAXIMUM_SIZE) { 194 | + this.items.clear(); 195 | + } 196 | + // Scissors end 197 | return this.items; 198 | } 199 | 200 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java 201 | index 9b1243d96e0694c62fc9e82e9be540bce0d2b3ad..2cf4a854a40aabbfff2f6ee4fb9e36e8d466afd5 100644 202 | --- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java 203 | +++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java 204 | @@ -1,5 +1,6 @@ 205 | package net.minecraft.world.level.block.entity; 206 | 207 | +import me.totalfreedom.scissors.NbtUtility; 208 | import net.minecraft.core.BlockPos; 209 | import net.minecraft.core.Direction; 210 | import net.minecraft.core.NonNullList; 211 | @@ -40,6 +41,17 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement 212 | private int maxStack = MAX_STACK; 213 | 214 | public List getContents() { 215 | + // Scissors start - Account for items inside containers 216 | + long total = 0; 217 | + 218 | + for (ItemStack item : this.items) { 219 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 220 | + } 221 | + 222 | + if (total > NbtUtility.MAXIMUM_SIZE) { 223 | + this.items.clear(); 224 | + } 225 | + // Scissors end 226 | return this.items; 227 | } 228 | 229 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java 230 | index 881379681c39230a00b3a1f11cd87498984396c7..8e1ef455c1b563844c416021c478b2a34b90c418 100644 231 | --- a/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java 232 | +++ b/src/main/java/net/minecraft/world/level/block/entity/DispenserBlockEntity.java 233 | @@ -1,5 +1,6 @@ 234 | package net.minecraft.world.level.block.entity; 235 | 236 | +import me.totalfreedom.scissors.NbtUtility; 237 | import net.minecraft.core.BlockPos; 238 | import net.minecraft.core.NonNullList; 239 | import net.minecraft.nbt.CompoundTag; 240 | @@ -28,6 +29,17 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { 241 | private int maxStack = MAX_STACK; 242 | 243 | public List getContents() { 244 | + // Scissors start - Account for items inside containers 245 | + long total = 0; 246 | + 247 | + for (ItemStack item : this.items) { 248 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 249 | + } 250 | + 251 | + if (total > NbtUtility.MAXIMUM_SIZE) { 252 | + this.items.clear(); 253 | + } 254 | + // Scissors end 255 | return this.items; 256 | } 257 | 258 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java 259 | index cdb739df2a285032d25d84f4464f202a7a3fa578..69845474c207220c0146891be90e3232ac8a3547 100644 260 | --- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java 261 | +++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java 262 | @@ -6,6 +6,8 @@ import java.util.function.BooleanSupplier; 263 | import java.util.stream.Collectors; 264 | import java.util.stream.IntStream; 265 | import javax.annotation.Nullable; 266 | + 267 | +import me.totalfreedom.scissors.NbtUtility; 268 | import net.minecraft.core.BlockPos; 269 | import net.minecraft.core.Direction; 270 | import net.minecraft.core.NonNullList; 271 | @@ -57,6 +59,17 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen 272 | private int maxStack = MAX_STACK; 273 | 274 | public List getContents() { 275 | + // Scissors start - Account for items inside containers 276 | + long total = 0; 277 | + 278 | + for (ItemStack item : this.items) { 279 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 280 | + } 281 | + 282 | + if (total > NbtUtility.MAXIMUM_SIZE) { 283 | + this.items.clear(); 284 | + } 285 | + // Scissors end 286 | return this.items; 287 | } 288 | 289 | diff --git a/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java 290 | index 1fa22445a4ecc8c08dbcf0cc6bd39dc5003604c4..c37f0f12283f528d16fd0450075eab1974ba5057 100644 291 | --- a/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java 292 | +++ b/src/main/java/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java 293 | @@ -4,6 +4,8 @@ import java.util.Iterator; 294 | import java.util.List; 295 | import java.util.stream.IntStream; 296 | import javax.annotation.Nullable; 297 | + 298 | +import me.totalfreedom.scissors.NbtUtility; 299 | import net.minecraft.core.BlockPos; 300 | import net.minecraft.core.Direction; 301 | import net.minecraft.core.NonNullList; 302 | @@ -61,6 +63,17 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl 303 | public boolean opened; 304 | 305 | public List getContents() { 306 | + // Scissors start - Account for items inside containers 307 | + long total = 0; 308 | + 309 | + for (ItemStack item : this.itemStacks) { 310 | + total += NbtUtility.getTagSize(item.getOrCreateTag()); 311 | + } 312 | + 313 | + if (total > NbtUtility.MAXIMUM_SIZE) { 314 | + this.itemStacks.clear(); 315 | + } 316 | + // Scissors end 317 | return this.itemStacks; 318 | } 319 | 320 | --------------------------------------------------------------------------------