From 7a6163b41def87c559f74dba84d79a21a78e3955 Mon Sep 17 00:00:00 2001 From: Space Walker <48224626+SpaceWalkerRS@users.noreply.github.com> Date: Sat, 7 May 2022 18:47:28 +0200 Subject: [PATCH] Add Alternate Current's redstone implementation as an alternative to Vanilla and Eigencraft's. (#7701) --- patches/server/0004-Paper-config-files.patch | 15 +- ...actus-bamboo-and-reed-growth-heights.patch | 4 +- ...figurable-baby-zombie-movement-speed.patch | 6 +- ...015-Configurable-fishing-time-ranges.patch | 4 +- ...d-mobs-to-jump-and-take-water-damage.patch | 4 +- ...-despawn-distances-for-living-entiti.patch | 6 +- ...8-Allow-for-toggling-of-spawn-chunks.patch | 4 +- ...ck-and-tnt-entities-at-the-specified.patch | 4 +- ...nfigurable-top-of-nether-void-damage.patch | 4 +- .../0031-Configurable-end-credits.patch | 4 +- patches/server/0033-Optimize-explosions.patch | 4 +- .../0034-Disable-explosion-knockback.patch | 4 +- patches/server/0035-Disable-thunder.patch | 4 +- .../server/0036-Disable-ice-and-snow.patch | 4 +- ...7-Configurable-mob-spawner-tick-rate.patch | 4 +- ...figurable-container-update-tick-rate.patch | 4 +- ...urable-Disabling-Cat-Chest-Detection.patch | 4 +- ...chunks-are-slime-spawn-chunks-toggle.patch | 4 +- ...dd-configurable-portal-search-radius.patch | 4 +- ...ble-inter-world-teleportation-safety.patch | 4 +- ...oreboards-for-non-players-by-default.patch | 4 +- ...urable-Non-Player-Arrow-Despawn-Rate.patch | 4 +- ...le-spawn-chances-for-skeleton-horses.patch | 4 +- ...74-Configurable-Chunk-Inhabited-Time.patch | 4 +- ...-Configurable-Grass-Spread-Tick-Rate.patch | 4 +- ...nilla-per-world-scoreboard-coloring-.patch | 4 +- ...-to-configure-frosted_ice-properties.patch | 4 +- ...-API-Replenishable-Lootables-Feature.patch | 4 +- ...4-Optional-TNT-doesn-t-move-in-water.patch | 4 +- ...a-from-ArmorStand-and-SpawnEgg-items.patch | 4 +- ...figurable-Cartographer-Treasure-Maps.patch | 4 +- .../server/0125-Cap-Entity-Collisions.patch | 4 +- ...ke-parrots-stay-on-shoulders-despite.patch | 4 +- ...urable-option-to-disable-creeper-lin.patch | 4 +- ...r-crits-helps-mitigate-hacked-client.patch | 4 +- ...urable-sprint-interruption-on-attack.patch | 4 +- ...0191-Block-Enderpearl-Travel-Exploit.patch | 4 +- ...e-shield-blocking-delay-configurable.patch | 4 +- ...to-disable-ender-dragon-legacy-check.patch | 4 +- ...t-armor-stands-from-doing-entity-loo.patch | 4 +- ...Allow-disabling-armour-stand-ticking.patch | 4 +- ...le-speed-for-water-flowing-over-lava.patch | 4 +- ...event-players-from-moving-into-unloa.patch | 4 +- ...le-Keep-Spawn-Loaded-range-per-world.patch | 4 +- ...al-Spawned-mobs-towards-natural-spaw.patch | 4 +- ...gurable-projectile-relative-velocity.patch | 4 +- ...d-option-to-disable-pillager-patrols.patch | 4 +- ...0337-Flat-bedrock-generator-settings.patch | 4 +- ...5656-Fix-Follow-Range-Initial-Target.patch | 4 +- .../0340-Duplicate-UUID-Resolve-Option.patch | 4 +- patches/server/0341-Optimize-Hoppers.patch | 4 +- .../0353-Increase-Light-Queue-Size.patch | 4 +- patches/server/0355-Anti-Xray.patch | 6 +- ...lement-alternative-item-despawn-rate.patch | 4 +- ...ement-optional-per-player-mob-spawns.patch | 4 +- ...n-to-nerf-pigmen-from-nether-portals.patch | 4 +- ...to-allow-iron-golems-to-spawn-in-air.patch | 4 +- ...-chance-of-villager-zombie-infection.patch | 6 +- ...-Add-tick-times-API-and-mspt-command.patch | 4 +- ...spawn-settings-and-per-player-option.patch | 4 +- ...ntom-creative-and-insomniac-controls.patch | 4 +- ...-maximum-exp-value-when-merging-orbs.patch | 4 +- ...unk-Unloads-based-on-Player-Movement.patch | 4 +- ...-incremental-chunk-and-player-saving.patch | 6 +- ...Add-zombie-targets-turtle-egg-config.patch | 6 +- .../0490-Optimize-redstone-algorithm.patch | 4 +- ...-Toggle-for-removing-existing-dragon.patch | 4 +- ...ing-Trader-spawn-rate-config-options.patch | 4 +- ...-should-not-bypass-cramming-gamerule.patch | 4 +- ...ing-zombie-villager-discount-exploit.patch | 4 +- ...mob-spawner-spawn-egg-transformation.patch | 4 +- ...ld-settings-for-mobs-picking-up-loot.patch | 4 +- ...onfigurable-door-breaking-difficulty.patch | 4 +- ...n-for-requiring-a-player-participant.patch | 4 +- ...0579-Configurable-max-leash-distance.patch | 4 +- ...le-for-always-placing-the-dragon-egg.patch | 4 +- ...disable-pathfinding-updates-on-block.patch | 4 +- ...-using-signs-inside-spawn-protection.patch | 4 +- ...616-Entity-load-save-limit-per-chunk.patch | 4 +- ...658-Limit-item-frame-cursors-on-maps.patch | 4 +- ...n-to-fix-items-merging-through-walls.patch | 4 +- .../0665-Fix-invulnerable-end-crystals.patch | 4 +- .../0671-add-per-world-spawn-limits.patch | 6 +- ...from-signs-not-firing-command-events.patch | 4 +- ...g-for-mobs-immune-to-default-effects.patch | 4 +- ...n-t-apply-cramming-damage-to-players.patch | 4 +- ...nd-timings-for-sensors-and-behaviors.patch | 4 +- ...g-option-for-Piglins-guarding-chests.patch | 4 +- ...tem-frame-map-cursor-update-interval.patch | 4 +- .../0784-Preserve-overstacked-loot.patch | 4 +- .../0791-Configurable-feature-seeds.patch | 4 +- ...de-unnecessary-itemmeta-from-clients.patch | 4 +- ...max-block-light-for-monster-spawning.patch | 4 +- ...ter-animal-spawn-height-configurable.patch | 4 +- ...-configurable-height-for-slime-spawn.patch | 4 +- ...nate-Current-redstone-implementation.patch | 2414 +++++++++++++++++ 96 files changed, 2619 insertions(+), 200 deletions(-) create mode 100644 patches/server/0905-Add-Alternate-Current-redstone-implementation.patch diff --git a/patches/server/0004-Paper-config-files.patch b/patches/server/0004-Paper-config-files.patch index 50e1a15e22..a8971ef784 100644 --- a/patches/server/0004-Paper-config-files.patch +++ b/patches/server/0004-Paper-config-files.patch @@ -298,7 +298,7 @@ index 0000000000000000000000000000000000000000..a7182a4c64980aa19b8493ac9c2bb762 +} diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..6f7681d8e03f15bee821b0c053ed64ad3afeb2a4 +index 0000000000000000000000000000000000000000..80a3d5890aab91e6a48d5734140187851106bde3 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java @@ -0,0 +1,188 @@ @@ -364,8 +364,8 @@ index 0000000000000000000000000000000000000000..6f7681d8e03f15bee821b0c053ed64ad + commands = new HashMap(); + commands.put("paper", new PaperCommand("paper")); + -+ version = getInt("config-version", 26); -+ set("config-version", 26); ++ version = getInt("config-version", 27); ++ set("config-version", 27); + readConfig(PaperConfig.class, null); + } + @@ -492,10 +492,10 @@ index 0000000000000000000000000000000000000000..6f7681d8e03f15bee821b0c053ed64ad +} diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java new file mode 100644 -index 0000000000000000000000000000000000000000..4adf44026fc6269934dfa4513f06a7f8a3b41f90 +index 0000000000000000000000000000000000000000..1dc56bee6827f6552cfa93a92fe8d0b5f94ab596 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +1,94 @@ +@@ -0,0 +1,99 @@ +package com.destroystokyo.paper; + +import java.util.List; @@ -536,6 +536,11 @@ index 0000000000000000000000000000000000000000..4adf44026fc6269934dfa4513f06a7f8 + } + } + ++ private void remove(String path) { ++ config.addDefault("world-settings.default." + path, null); ++ set(path, null); ++ } ++ + public void removeOldValues() { + boolean needsSave = false; + diff --git a/patches/server/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch index 43e88d37d9..089185b9f7 100644 --- a/patches/server/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch +++ b/patches/server/0013-Configurable-cactus-bamboo-and-reed-growth-heights.patch @@ -7,10 +7,10 @@ Bamboo - Both the minimum fully-grown heights and the maximum are configurable - Machine_Maker diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4adf44026fc6269934dfa4513f06a7f8a3b41f90..791ccdebd5d37afd83eb87671034b3553e305f8f 100644 +index 1dc56bee6827f6552cfa93a92fe8d0b5f94ab596..e8b2ad7b454113c279733fb8f385d0d3f217e0f5 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -91,4 +91,16 @@ public class PaperWorldConfig { +@@ -96,4 +96,16 @@ public class PaperWorldConfig { config.addDefault("world-settings.default." + path, def.stream().map(Enum::name).collect(Collectors.toList())); return ((List) (config.getList("world-settings." + worldName + "." + path, config.getList("world-settings.default." + path)))).stream().map(s -> Enum.valueOf(type, s)).collect(Collectors.toList()); } diff --git a/patches/server/0014-Configurable-baby-zombie-movement-speed.patch b/patches/server/0014-Configurable-baby-zombie-movement-speed.patch index cbdf1e180c..c9304b1dcb 100644 --- a/patches/server/0014-Configurable-baby-zombie-movement-speed.patch +++ b/patches/server/0014-Configurable-baby-zombie-movement-speed.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable baby zombie movement speed diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 791ccdebd5d37afd83eb87671034b3553e305f8f..ec3fb557fa31b153de20c4990066182a774dd489 100644 +index e8b2ad7b454113c279733fb8f385d0d3f217e0f5..aba9f77878bd5475a63af1fa3f60580674ea63ad 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -103,4 +103,15 @@ public class PaperWorldConfig { +@@ -108,4 +108,15 @@ public class PaperWorldConfig { bambooMinHeight = getInt("max-growth-height.bamboo.min", 11); log("Max height for cactus growth " + cactusMaxHeight + ". Max height for reed growth " + reedMaxHeight + ". Max height for bamboo growth " + bambooMaxHeight + ". Min height for fully-grown bamboo " + bambooMinHeight + "."); } @@ -25,7 +25,7 @@ index 791ccdebd5d37afd83eb87671034b3553e305f8f..ec3fb557fa31b153de20c4990066182a + } } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index f83b3d750b97c987748b940b810d5a88ee355049..45cfbf30d27139036dee5379a88ed24a5cee51b4 100644 +index 627aeb45342c2804f911572056a63aa1cb0110e7..953f138b6cd48cc94bc23a4321a9684b4214637e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -76,7 +76,7 @@ import org.bukkit.event.entity.EntityTransformEvent; diff --git a/patches/server/0015-Configurable-fishing-time-ranges.patch b/patches/server/0015-Configurable-fishing-time-ranges.patch index 4b09a21b14..e9af278520 100644 --- a/patches/server/0015-Configurable-fishing-time-ranges.patch +++ b/patches/server/0015-Configurable-fishing-time-ranges.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable fishing time ranges diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ec3fb557fa31b153de20c4990066182a774dd489..5896b4e4646d722db5622a424fa26f42d3f8d9ff 100644 +index aba9f77878bd5475a63af1fa3f60580674ea63ad..f92f936c4b7e4fea63eef65c4ae8c10eeacb36b0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -114,4 +114,12 @@ public class PaperWorldConfig { +@@ -119,4 +119,12 @@ public class PaperWorldConfig { log("Baby zombies will move at the speed of " + babyZombieMovementModifier); } diff --git a/patches/server/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch index df382a396d..de6f39ee30 100644 --- a/patches/server/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch +++ b/patches/server/0016-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow nerfed mobs to jump and take water damage diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5896b4e4646d722db5622a424fa26f42d3f8d9ff..0a6e98ca5534430540044a32c280e5680ac9a28f 100644 +index f92f936c4b7e4fea63eef65c4ae8c10eeacb36b0..adb1f1bf96bd37b571fb53419db063d79a041bbf 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -122,4 +122,9 @@ public class PaperWorldConfig { +@@ -127,4 +127,9 @@ public class PaperWorldConfig { fishingMaxTicks = getInt("fishing-time-range.MaximumTicks", 600); log("Fishing time ranges are between " + fishingMinTicks +" and " + fishingMaxTicks + " ticks"); } diff --git a/patches/server/0017-Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server/0017-Add-configurable-despawn-distances-for-living-entiti.patch index 8e7a6d618b..05fc69badb 100644 --- a/patches/server/0017-Add-configurable-despawn-distances-for-living-entiti.patch +++ b/patches/server/0017-Add-configurable-despawn-distances-for-living-entiti.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add configurable despawn distances for living entities diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0a6e98ca5534430540044a32c280e5680ac9a28f..6ee62d06cc2b59c06d0f7acfb59384075aa6521c 100644 +index adb1f1bf96bd37b571fb53419db063d79a041bbf..309fdf93b0a148d00cda58ffd31557f349d12907 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -3,6 +3,9 @@ package com.destroystokyo.paper; @@ -18,7 +18,7 @@ index 0a6e98ca5534430540044a32c280e5680ac9a28f..6ee62d06cc2b59c06d0f7acfb5938407 import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -41,6 +44,13 @@ public class PaperWorldConfig { +@@ -46,6 +49,13 @@ public class PaperWorldConfig { public void removeOldValues() { boolean needsSave = false; @@ -32,7 +32,7 @@ index 0a6e98ca5534430540044a32c280e5680ac9a28f..6ee62d06cc2b59c06d0f7acfb5938407 if (needsSave) { saveConfig(); } -@@ -127,4 +137,31 @@ public class PaperWorldConfig { +@@ -132,4 +142,31 @@ public class PaperWorldConfig { private void nerfedMobsShouldJump() { nerfedMobsShouldJump = getBoolean("spawner-nerfed-mobs-should-jump", false); } diff --git a/patches/server/0018-Allow-for-toggling-of-spawn-chunks.patch b/patches/server/0018-Allow-for-toggling-of-spawn-chunks.patch index da729250d4..f3cc095d85 100644 --- a/patches/server/0018-Allow-for-toggling-of-spawn-chunks.patch +++ b/patches/server/0018-Allow-for-toggling-of-spawn-chunks.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow for toggling of spawn chunks diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6ee62d06cc2b59c06d0f7acfb59384075aa6521c..9b908c5c66dc454faa479430a908dda0745638c8 100644 +index 309fdf93b0a148d00cda58ffd31557f349d12907..9d1039c25423fde234962533bddc3f965992716f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -164,4 +164,10 @@ public class PaperWorldConfig { +@@ -169,4 +169,10 @@ public class PaperWorldConfig { hardDespawnDistances.put(category, hardDistance); } } diff --git a/patches/server/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch index 1d0e2d4bc8..1f376dec56 100644 --- a/patches/server/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch +++ b/patches/server/0019-Drop-falling-block-and-tnt-entities-at-the-specified.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Drop falling block and tnt entities at the specified height * Dec 2, 2020 Added tnt nerf for tnt minecarts - Machine_Maker diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9b908c5c66dc454faa479430a908dda0745638c8..6dec1bb96d695f28aae6517e4d78249169d2351a 100644 +index 9d1039c25423fde234962533bddc3f965992716f..70bcd7cae2777c2c7fbf995b8783ece31d9349e5 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -170,4 +170,14 @@ public class PaperWorldConfig { +@@ -175,4 +175,14 @@ public class PaperWorldConfig { keepSpawnInMemory = getBoolean("keep-spawn-loaded", true); log("Keep spawn chunk loaded: " + keepSpawnInMemory); } diff --git a/patches/server/0028-Configurable-top-of-nether-void-damage.patch b/patches/server/0028-Configurable-top-of-nether-void-damage.patch index 4eecf0de5a..681cbe3812 100644 --- a/patches/server/0028-Configurable-top-of-nether-void-damage.patch +++ b/patches/server/0028-Configurable-top-of-nether-void-damage.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable top of nether void damage diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6dec1bb96d695f28aae6517e4d78249169d2351a..1b090f2e38a8857ef74403e1f3db8c2ba7127297 100644 +index 70bcd7cae2777c2c7fbf995b8783ece31d9349e5..0ba54e24944c9e30bc06dc2556e9c856d2b335bc 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -180,4 +180,19 @@ public class PaperWorldConfig { +@@ -185,4 +185,19 @@ public class PaperWorldConfig { if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf); if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf); } diff --git a/patches/server/0031-Configurable-end-credits.patch b/patches/server/0031-Configurable-end-credits.patch index af70937d19..32316f03ed 100644 --- a/patches/server/0031-Configurable-end-credits.patch +++ b/patches/server/0031-Configurable-end-credits.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable end credits diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1b090f2e38a8857ef74403e1f3db8c2ba7127297..bc35bdd9cbd544ae2ab27ad042d7d1b3166db9a6 100644 +index 0ba54e24944c9e30bc06dc2556e9c856d2b335bc..cb6add86fadcb4684ed917a8b05ada84a75c0a27 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -195,4 +195,10 @@ public class PaperWorldConfig { +@@ -200,4 +200,10 @@ public class PaperWorldConfig { } } } diff --git a/patches/server/0033-Optimize-explosions.patch b/patches/server/0033-Optimize-explosions.patch index 5d241f7a2b..2a3b7b10f2 100644 --- a/patches/server/0033-Optimize-explosions.patch +++ b/patches/server/0033-Optimize-explosions.patch @@ -10,10 +10,10 @@ This patch adds a per-tick cache that is used for storing and retrieving an entity's exposure during an explosion. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bc35bdd9cbd544ae2ab27ad042d7d1b3166db9a6..2b0a75dc2e292e655ca3300f64bc1211b3adeceb 100644 +index cb6add86fadcb4684ed917a8b05ada84a75c0a27..e4873fa644790d6d1db0160688123fc5a60d0bb0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -201,4 +201,10 @@ public class PaperWorldConfig { +@@ -206,4 +206,10 @@ public class PaperWorldConfig { disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false); log("End credits disabled: " + disableEndCredits); } diff --git a/patches/server/0034-Disable-explosion-knockback.patch b/patches/server/0034-Disable-explosion-knockback.patch index 8a4aeab17b..1a5a11cfe6 100644 --- a/patches/server/0034-Disable-explosion-knockback.patch +++ b/patches/server/0034-Disable-explosion-knockback.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable explosion knockback diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2b0a75dc2e292e655ca3300f64bc1211b3adeceb..5cae4a5caf9aba8c0e99f1cb6badc5e8374862c8 100644 +index e4873fa644790d6d1db0160688123fc5a60d0bb0..230f89329c31a65813b25addb4f6552e3f181069 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -207,4 +207,9 @@ public class PaperWorldConfig { +@@ -212,4 +212,9 @@ public class PaperWorldConfig { optimizeExplosions = getBoolean("optimize-explosions", false); log("Optimize explosions: " + optimizeExplosions); } diff --git a/patches/server/0035-Disable-thunder.patch b/patches/server/0035-Disable-thunder.patch index 9026d6d2e1..8966f656cd 100644 --- a/patches/server/0035-Disable-thunder.patch +++ b/patches/server/0035-Disable-thunder.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable thunder diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5cae4a5caf9aba8c0e99f1cb6badc5e8374862c8..1a9b4b08ea906adbfa25c3963a4634871d7ca2f6 100644 +index 230f89329c31a65813b25addb4f6552e3f181069..5019413dc5973dcc8fe0f1381ba2463862499b88 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -212,4 +212,9 @@ public class PaperWorldConfig { +@@ -217,4 +217,9 @@ public class PaperWorldConfig { private void disableExplosionKnockback(){ disableExplosionKnockback = getBoolean("disable-explosion-knockback", false); } diff --git a/patches/server/0036-Disable-ice-and-snow.patch b/patches/server/0036-Disable-ice-and-snow.patch index 0755be7364..2cdf33a325 100644 --- a/patches/server/0036-Disable-ice-and-snow.patch +++ b/patches/server/0036-Disable-ice-and-snow.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable ice and snow diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1a9b4b08ea906adbfa25c3963a4634871d7ca2f6..ceb1602afb90fc0a23d6cc8d22fc85fab3b8da14 100644 +index 5019413dc5973dcc8fe0f1381ba2463862499b88..38b8b7bd59381c13a919c9b2e125d804be9b6e89 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -217,4 +217,9 @@ public class PaperWorldConfig { +@@ -222,4 +222,9 @@ public class PaperWorldConfig { private void disableThunder() { disableThunder = getBoolean("disable-thunder", false); } diff --git a/patches/server/0037-Configurable-mob-spawner-tick-rate.patch b/patches/server/0037-Configurable-mob-spawner-tick-rate.patch index dfef31d530..d5a4f20fd6 100644 --- a/patches/server/0037-Configurable-mob-spawner-tick-rate.patch +++ b/patches/server/0037-Configurable-mob-spawner-tick-rate.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable mob spawner tick rate diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ceb1602afb90fc0a23d6cc8d22fc85fab3b8da14..e7b7f0a1a35f782a0da4627b4f02e673ca73693e 100644 +index 38b8b7bd59381c13a919c9b2e125d804be9b6e89..6b527d72309a38eec35de5d8d30a9def9f6df783 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -222,4 +222,9 @@ public class PaperWorldConfig { +@@ -227,4 +227,9 @@ public class PaperWorldConfig { private void disableIceAndSnow(){ disableIceAndSnow = getBoolean("disable-ice-and-snow", false); } diff --git a/patches/server/0041-Configurable-container-update-tick-rate.patch b/patches/server/0041-Configurable-container-update-tick-rate.patch index 5711ea74a5..f6189d11eb 100644 --- a/patches/server/0041-Configurable-container-update-tick-rate.patch +++ b/patches/server/0041-Configurable-container-update-tick-rate.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable container update tick rate diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e7b7f0a1a35f782a0da4627b4f02e673ca73693e..1b51f717ec2a0538d9037dd1d4328030bd9122c8 100644 +index 6b527d72309a38eec35de5d8d30a9def9f6df783..421e51892ca431409b9b52e7901ca42c44d9e6dd 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -227,4 +227,9 @@ public class PaperWorldConfig { +@@ -232,4 +232,9 @@ public class PaperWorldConfig { private void mobSpawnerTickRate() { mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); } diff --git a/patches/server/0045-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server/0045-Configurable-Disabling-Cat-Chest-Detection.patch index f340deebe8..a890564ea6 100644 --- a/patches/server/0045-Configurable-Disabling-Cat-Chest-Detection.patch +++ b/patches/server/0045-Configurable-Disabling-Cat-Chest-Detection.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Configurable Disabling Cat Chest Detection Offers a gameplay feature to stop cats from blocking chests diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1b51f717ec2a0538d9037dd1d4328030bd9122c8..990757a8bbd27fa102c9b408246ed14d97a340dc 100644 +index 421e51892ca431409b9b52e7901ca42c44d9e6dd..35a693ababf975c747ff2411d0fce7f7b1e1950b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -232,4 +232,9 @@ public class PaperWorldConfig { +@@ -237,4 +237,9 @@ public class PaperWorldConfig { private void containerUpdateTickRate() { containerUpdateTickRate = getInt("container-update-tick-rate", 1); } diff --git a/patches/server/0047-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server/0047-All-chunks-are-slime-spawn-chunks-toggle.patch index 36066b8123..ae1354d496 100644 --- a/patches/server/0047-All-chunks-are-slime-spawn-chunks-toggle.patch +++ b/patches/server/0047-All-chunks-are-slime-spawn-chunks-toggle.patch @@ -5,10 +5,10 @@ Subject: [PATCH] All chunks are slime spawn chunks toggle diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 990757a8bbd27fa102c9b408246ed14d97a340dc..1e3c39f0eeeb07f8d49e3651b18a152db9ccba7b 100644 +index 35a693ababf975c747ff2411d0fce7f7b1e1950b..21b1430b9565e87ac052bc75ba013cf94176d6c9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -237,4 +237,9 @@ public class PaperWorldConfig { +@@ -242,4 +242,9 @@ public class PaperWorldConfig { private void disableChestCatDetection() { disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); } diff --git a/patches/server/0052-Add-configurable-portal-search-radius.patch b/patches/server/0052-Add-configurable-portal-search-radius.patch index 53fe945c50..b9cf0187ab 100644 --- a/patches/server/0052-Add-configurable-portal-search-radius.patch +++ b/patches/server/0052-Add-configurable-portal-search-radius.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add configurable portal search radius diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1e3c39f0eeeb07f8d49e3651b18a152db9ccba7b..c248b66486044150c64eaddbef85fa6644494212 100644 +index 21b1430b9565e87ac052bc75ba013cf94176d6c9..d05dd815900dbdc78d1315eb13212d4e7cdf04d9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -242,4 +242,13 @@ public class PaperWorldConfig { +@@ -247,4 +247,13 @@ public class PaperWorldConfig { private void allChunksAreSlimeChunks() { allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); } diff --git a/patches/server/0054-Configurable-inter-world-teleportation-safety.patch b/patches/server/0054-Configurable-inter-world-teleportation-safety.patch index 06e792659e..56ce3f28ea 100644 --- a/patches/server/0054-Configurable-inter-world-teleportation-safety.patch +++ b/patches/server/0054-Configurable-inter-world-teleportation-safety.patch @@ -16,10 +16,10 @@ The wanted destination was on top of the emerald block however the player ended This only is the case if the player is teleporting between worlds. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c248b66486044150c64eaddbef85fa6644494212..ada624b5f58381122e59568c2087cf38fd2baf3e 100644 +index d05dd815900dbdc78d1315eb13212d4e7cdf04d9..b0bb68bdbd1a64a639c5fd2173c86f8e52291c20 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -251,4 +251,9 @@ public class PaperWorldConfig { +@@ -256,4 +256,9 @@ public class PaperWorldConfig { portalCreateRadius = getInt("portal-create-radius", 16); portalSearchVanillaDimensionScaling = getBoolean("portal-search-vanilla-dimension-scaling", true); } diff --git a/patches/server/0057-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server/0057-Disable-Scoreboards-for-non-players-by-default.patch index 3b46f159ed..4e73445538 100644 --- a/patches/server/0057-Disable-Scoreboards-for-non-players-by-default.patch +++ b/patches/server/0057-Disable-Scoreboards-for-non-players-by-default.patch @@ -11,10 +11,10 @@ So avoid looking up scoreboards and short circuit to the "not on a team" logic which is most likely to be true. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ada624b5f58381122e59568c2087cf38fd2baf3e..5b55fce59db9ac3ab6030ebe8374c5147535d773 100644 +index b0bb68bdbd1a64a639c5fd2173c86f8e52291c20..7bd8c3a02a3024aea72b70366569dc399dd4f9a6 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -256,4 +256,9 @@ public class PaperWorldConfig { +@@ -261,4 +261,9 @@ public class PaperWorldConfig { private void disableTeleportationSuffocationCheck() { disableTeleportationSuffocationCheck = getBoolean("disable-teleportation-suffocation-check", false); } diff --git a/patches/server/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch index 9566e5a378..ba0480b581 100644 --- a/patches/server/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch +++ b/patches/server/0065-Configurable-Non-Player-Arrow-Despawn-Rate.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Configurable Non Player Arrow Despawn Rate Can set a much shorter despawn rate for arrows that players can not pick up. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5b55fce59db9ac3ab6030ebe8374c5147535d773..71c672eafdce3547eaeb8e31fddcb142ad213094 100644 +index 7bd8c3a02a3024aea72b70366569dc399dd4f9a6..b38dd476f9fc08173230e0108f9d8addc65b1977 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -261,4 +261,19 @@ public class PaperWorldConfig { +@@ -266,4 +266,19 @@ public class PaperWorldConfig { private void nonPlayerEntitiesOnScoreboards() { nonPlayerEntitiesOnScoreboards = getBoolean("allow-non-player-entities-on-scoreboards", false); } diff --git a/patches/server/0070-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server/0070-Configurable-spawn-chances-for-skeleton-horses.patch index 453b58dc0e..33b3079a12 100644 --- a/patches/server/0070-Configurable-spawn-chances-for-skeleton-horses.patch +++ b/patches/server/0070-Configurable-spawn-chances-for-skeleton-horses.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable spawn chances for skeleton horses diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 71c672eafdce3547eaeb8e31fddcb142ad213094..aa8cd5965632626e4cbd4952acf9b349f79b2b1c 100644 +index b38dd476f9fc08173230e0108f9d8addc65b1977..1162490776712755dad0ec25b40a1420c0a01488 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -276,4 +276,12 @@ public class PaperWorldConfig { +@@ -281,4 +281,12 @@ public class PaperWorldConfig { log("Non Player Arrow Despawn Rate: " + nonPlayerArrowDespawnRate); log("Creative Arrow Despawn Rate: " + creativeArrowDespawnRate); } diff --git a/patches/server/0074-Configurable-Chunk-Inhabited-Time.patch b/patches/server/0074-Configurable-Chunk-Inhabited-Time.patch index bf6d556f43..4d37e8c5ad 100644 --- a/patches/server/0074-Configurable-Chunk-Inhabited-Time.patch +++ b/patches/server/0074-Configurable-Chunk-Inhabited-Time.patch @@ -11,10 +11,10 @@ For people who want all chunks to be treated equally, you can chose a fixed valu This allows to fine-tune vanilla gameplay. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index aa8cd5965632626e4cbd4952acf9b349f79b2b1c..e7534ed3f995be64c99399ab76e98086cf37bb7f 100644 +index 1162490776712755dad0ec25b40a1420c0a01488..1471965911d9fd3bfad9c4d85607c02ec19fbf1f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -284,4 +284,14 @@ public class PaperWorldConfig { +@@ -289,4 +289,14 @@ public class PaperWorldConfig { skeleHorseSpawnChance = 0.01D; // Vanilla value } } diff --git a/patches/server/0079-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server/0079-Configurable-Grass-Spread-Tick-Rate.patch index cc11565d1c..7add776d6e 100644 --- a/patches/server/0079-Configurable-Grass-Spread-Tick-Rate.patch +++ b/patches/server/0079-Configurable-Grass-Spread-Tick-Rate.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable Grass Spread Tick Rate diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index e7534ed3f995be64c99399ab76e98086cf37bb7f..c008f1f7f0a1e1b8bf34f2702cb44c5f9d62f848 100644 +index 1471965911d9fd3bfad9c4d85607c02ec19fbf1f..1496ad80007b93255d105942fef19f4f1a069206 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -294,4 +294,10 @@ public class PaperWorldConfig { +@@ -299,4 +299,10 @@ public class PaperWorldConfig { } fixedInhabitedTime = getInt("fixed-chunk-inhabited-time", -1); } diff --git a/patches/server/0082-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server/0082-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch index f38c57fac2..64389ced35 100644 --- a/patches/server/0082-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch +++ b/patches/server/0082-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch @@ -12,10 +12,10 @@ for this on CB at one point but I can't find it. We may need to do this ourselves at some point in the future. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index c008f1f7f0a1e1b8bf34f2702cb44c5f9d62f848..97693c33ba5a7efe40f05e0494216ee105e8bf74 100644 +index 1496ad80007b93255d105942fef19f4f1a069206..f0be60905effc3489ec0050cc456ae884b2b5b90 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -300,4 +300,9 @@ public class PaperWorldConfig { +@@ -305,4 +305,9 @@ public class PaperWorldConfig { grassUpdateRate = Math.max(0, getInt("grass-spread-tick-rate", grassUpdateRate)); log("Grass Spread Tick Rate: " + grassUpdateRate); } diff --git a/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch index 1d79f6db2a..c21cf21fdd 100644 --- a/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch +++ b/patches/server/0087-Add-ability-to-configure-frosted_ice-properties.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add ability to configure frosted_ice properties diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 97693c33ba5a7efe40f05e0494216ee105e8bf74..7d92c9830206dacf34fc0f2f02d9453b3e0c0a5e 100644 +index f0be60905effc3489ec0050cc456ae884b2b5b90..62437bd21994781379913e1bd3477b33cead2c18 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -305,4 +305,14 @@ public class PaperWorldConfig { +@@ -310,4 +310,14 @@ public class PaperWorldConfig { private void useVanillaScoreboardColoring() { useVanillaScoreboardColoring = getBoolean("use-vanilla-world-scoreboard-name-coloring", false); } diff --git a/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch index 5f0cd44b2b..6c09b70158 100644 --- a/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch +++ b/patches/server/0090-LootTable-API-Replenishable-Lootables-Feature.patch @@ -11,10 +11,10 @@ This feature is good for long term worlds so that newer players do not suffer with "Every chest has been looted" diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7d92c9830206dacf34fc0f2f02d9453b3e0c0a5e..7661e41950c38bce94a2c7de4269ba6ebb2f6c52 100644 +index 62437bd21994781379913e1bd3477b33cead2c18..929a9b775ddb10397929c2c5ce25cf03eaec4b1a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -315,4 +315,26 @@ public class PaperWorldConfig { +@@ -320,4 +320,26 @@ public class PaperWorldConfig { this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); } diff --git a/patches/server/0094-Optional-TNT-doesn-t-move-in-water.patch b/patches/server/0094-Optional-TNT-doesn-t-move-in-water.patch index 64982119f2..63f2f5d6b4 100644 --- a/patches/server/0094-Optional-TNT-doesn-t-move-in-water.patch +++ b/patches/server/0094-Optional-TNT-doesn-t-move-in-water.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Optional TNT doesn't move in water diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7661e41950c38bce94a2c7de4269ba6ebb2f6c52..d7734fbc6b684b14bc32c94e65947fb41aae126a 100644 +index 929a9b775ddb10397929c2c5ce25cf03eaec4b1a..97b02b5a4808fc0b7fd2d2a88817716cba61054b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -337,4 +337,14 @@ public class PaperWorldConfig { +@@ -342,4 +342,14 @@ public class PaperWorldConfig { ); } } diff --git a/patches/server/0106-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch b/patches/server/0106-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch index bd4dbdf718..b0972c4a15 100644 --- a/patches/server/0106-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch +++ b/patches/server/0106-Filter-bad-data-from-ArmorStand-and-SpawnEgg-items.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Filter bad data from ArmorStand and SpawnEgg items diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d7734fbc6b684b14bc32c94e65947fb41aae126a..7320f07beffee60fe3c49016daf7a98658879a27 100644 +index 97b02b5a4808fc0b7fd2d2a88817716cba61054b..fd64a7c1ee7617285990fd5066f768f0bcf2dbcf 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -347,4 +347,12 @@ public class PaperWorldConfig { +@@ -352,4 +352,12 @@ public class PaperWorldConfig { preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false); log("Prevent TNT from moving in water: " + preventTntFromMovingInWater); } diff --git a/patches/server/0114-Configurable-Cartographer-Treasure-Maps.patch b/patches/server/0114-Configurable-Cartographer-Treasure-Maps.patch index 08c18d59bd..7697c114f1 100644 --- a/patches/server/0114-Configurable-Cartographer-Treasure-Maps.patch +++ b/patches/server/0114-Configurable-Cartographer-Treasure-Maps.patch @@ -9,10 +9,10 @@ Also allow turning off treasure maps all together as they can eat up Map ID's which are limited in quantity. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7320f07beffee60fe3c49016daf7a98658879a27..5183c756289db3600d04d473c20d08768af91ea9 100644 +index fd64a7c1ee7617285990fd5066f768f0bcf2dbcf..cfe37643eea0fbff097ecf770977f9fefd94dece 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -355,4 +355,14 @@ public class PaperWorldConfig { +@@ -360,4 +360,14 @@ public class PaperWorldConfig { Bukkit.getLogger().warning("Spawn Egg and Armor Stand NBT filtering disabled, this is a potential security risk"); } } diff --git a/patches/server/0125-Cap-Entity-Collisions.patch b/patches/server/0125-Cap-Entity-Collisions.patch index 5e456a904c..c313a37acf 100644 --- a/patches/server/0125-Cap-Entity-Collisions.patch +++ b/patches/server/0125-Cap-Entity-Collisions.patch @@ -12,10 +12,10 @@ just as it does in Vanilla, but entity pushing logic will be capped. You can set this to 0 to disable collisions. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5183c756289db3600d04d473c20d08768af91ea9..72501b05d1d5d9304e4ac31bbf694f5ca1637c0f 100644 +index cfe37643eea0fbff097ecf770977f9fefd94dece..9a3940e93e87a0b2b17d4a35bd71f0a40a139cea 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -365,4 +365,10 @@ public class PaperWorldConfig { +@@ -370,4 +370,10 @@ public class PaperWorldConfig { log("Treasure Maps will return already discovered locations"); } } diff --git a/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch index 536d61716f..f1564bb7c1 100644 --- a/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ b/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -11,10 +11,10 @@ I suspect Mojang may switch to this behavior before full release. To be converted into a Paper-API event at some point in the future? diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 72501b05d1d5d9304e4ac31bbf694f5ca1637c0f..f459b23282e5353f0f57bd228af7e8d53050eda9 100644 +index 9a3940e93e87a0b2b17d4a35bd71f0a40a139cea..49c4d84266c000b26dac30074076057bd1e6e119 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -371,4 +371,10 @@ public class PaperWorldConfig { +@@ -376,4 +376,10 @@ public class PaperWorldConfig { maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", this.maxCollisionsPerEntity, false) ); log( "Max Entity Collisions: " + maxCollisionsPerEntity ); } diff --git a/patches/server/0133-provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server/0133-provide-a-configurable-option-to-disable-creeper-lin.patch index 94e912f456..7efea35611 100644 --- a/patches/server/0133-provide-a-configurable-option-to-disable-creeper-lin.patch +++ b/patches/server/0133-provide-a-configurable-option-to-disable-creeper-lin.patch @@ -6,10 +6,10 @@ Subject: [PATCH] provide a configurable option to disable creeper lingering diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f459b23282e5353f0f57bd228af7e8d53050eda9..2c92d3d924fa132937576c24da26e2a8f72f601e 100644 +index 49c4d84266c000b26dac30074076057bd1e6e119..9ef33cc086fee0742ca5c3ad609fc60040e04f41 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -377,4 +377,10 @@ public class PaperWorldConfig { +@@ -382,4 +382,10 @@ public class PaperWorldConfig { parrotsHangOnBetter = getBoolean("parrots-are-unaffected-by-player-movement", false); log("Parrots are unaffected by player movement: " + parrotsHangOnBetter); } diff --git a/patches/server/0175-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server/0175-Toggleable-player-crits-helps-mitigate-hacked-client.patch index a541c92642..3fa69d8a40 100644 --- a/patches/server/0175-Toggleable-player-crits-helps-mitigate-hacked-client.patch +++ b/patches/server/0175-Toggleable-player-crits-helps-mitigate-hacked-client.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Toggleable player crits, helps mitigate hacked clients. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2c92d3d924fa132937576c24da26e2a8f72f601e..207bef30c34e368066f4058dd28dd12fdbac5d34 100644 +index 9ef33cc086fee0742ca5c3ad609fc60040e04f41..558912febee89f2626795ee2688352c738dc4b7b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -238,6 +238,11 @@ public class PaperWorldConfig { +@@ -243,6 +243,11 @@ public class PaperWorldConfig { disableChestCatDetection = getBoolean("game-mechanics.disable-chest-cat-detection", false); } diff --git a/patches/server/0187-Configurable-sprint-interruption-on-attack.patch b/patches/server/0187-Configurable-sprint-interruption-on-attack.patch index 27f3182bec..5ecc2e4e16 100644 --- a/patches/server/0187-Configurable-sprint-interruption-on-attack.patch +++ b/patches/server/0187-Configurable-sprint-interruption-on-attack.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Configurable sprint interruption on attack If the sprint interruption is disabled players continue sprinting when they attack entities. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 207bef30c34e368066f4058dd28dd12fdbac5d34..ef9f6712046a22a8d0dfcf95d8e2d12403345532 100644 +index 558912febee89f2626795ee2688352c738dc4b7b..c795973a1d52a60f731b14b1dbfb2dc7429dc8a5 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -388,4 +388,9 @@ public class PaperWorldConfig { +@@ -393,4 +393,9 @@ public class PaperWorldConfig { disableCreeperLingeringEffect = getBoolean("disable-creeper-lingering-effect", false); log("Creeper lingering effect: " + disableCreeperLingeringEffect); } diff --git a/patches/server/0191-Block-Enderpearl-Travel-Exploit.patch b/patches/server/0191-Block-Enderpearl-Travel-Exploit.patch index ed081046b6..3cffff648f 100644 --- a/patches/server/0191-Block-Enderpearl-Travel-Exploit.patch +++ b/patches/server/0191-Block-Enderpearl-Travel-Exploit.patch @@ -12,10 +12,10 @@ This disables that by not saving the thrower when the chunk is unloaded. This is mainly useful for survival servers that do not allow freeform teleporting. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ef9f6712046a22a8d0dfcf95d8e2d12403345532..ea426792b751fd7591bf09f2256dd6bdd31fac06 100644 +index c795973a1d52a60f731b14b1dbfb2dc7429dc8a5..7a25d602a016c4113cf93f58fa5dfcb8613067fe 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -393,4 +393,10 @@ public class PaperWorldConfig { +@@ -398,4 +398,10 @@ public class PaperWorldConfig { private void disableSprintInterruptionOnAttack() { disableSprintInterruptionOnAttack = getBoolean("game-mechanics.disable-sprint-interruption-on-attack", false); } diff --git a/patches/server/0205-Make-shield-blocking-delay-configurable.patch b/patches/server/0205-Make-shield-blocking-delay-configurable.patch index 8dcd253d10..7a558469ee 100644 --- a/patches/server/0205-Make-shield-blocking-delay-configurable.patch +++ b/patches/server/0205-Make-shield-blocking-delay-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make shield blocking delay configurable diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ea426792b751fd7591bf09f2256dd6bdd31fac06..50ad52d33de2eb977e1fec50c0e9ca5448900c4b 100644 +index 7a25d602a016c4113cf93f58fa5dfcb8613067fe..9b2f958b70eaf44d3686c5dafc29f81fa23a8979 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -399,4 +399,9 @@ public class PaperWorldConfig { +@@ -404,4 +404,9 @@ public class PaperWorldConfig { disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit); log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled")); } diff --git a/patches/server/0212-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/0212-Add-config-to-disable-ender-dragon-legacy-check.patch index 2e506a8d7c..5b73d41538 100644 --- a/patches/server/0212-Add-config-to-disable-ender-dragon-legacy-check.patch +++ b/patches/server/0212-Add-config-to-disable-ender-dragon-legacy-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add config to disable ender dragon legacy check diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 50ad52d33de2eb977e1fec50c0e9ca5448900c4b..4b73a3ff72db0135273365b95a2d097d3c34c7c4 100644 +index 9b2f958b70eaf44d3686c5dafc29f81fa23a8979..e457ffae1c5c7ce3e14205af7088ed1206a6b36c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -404,4 +404,9 @@ public class PaperWorldConfig { +@@ -409,4 +409,9 @@ public class PaperWorldConfig { private void shieldBlockingDelay() { shieldBlockingDelay = getInt("game-mechanics.shield-blocking-delay", 5); } diff --git a/patches/server/0225-Option-to-prevent-armor-stands-from-doing-entity-loo.patch b/patches/server/0225-Option-to-prevent-armor-stands-from-doing-entity-loo.patch index e685b949d8..33a31035bd 100644 --- a/patches/server/0225-Option-to-prevent-armor-stands-from-doing-entity-loo.patch +++ b/patches/server/0225-Option-to-prevent-armor-stands-from-doing-entity-loo.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option to prevent armor stands from doing entity lookups diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4b73a3ff72db0135273365b95a2d097d3c34c7c4..1cf6eb1b578561dfd9e734843fb87e477c7bde9e 100644 +index e457ffae1c5c7ce3e14205af7088ed1206a6b36c..6f0d3af10905161d9359d67ac17ce32da923d447 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -409,4 +409,9 @@ public class PaperWorldConfig { +@@ -414,4 +414,9 @@ public class PaperWorldConfig { private void scanForLegacyEnderDragon() { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } diff --git a/patches/server/0227-Allow-disabling-armour-stand-ticking.patch b/patches/server/0227-Allow-disabling-armour-stand-ticking.patch index ac3d013f29..a1bd82fb0c 100644 --- a/patches/server/0227-Allow-disabling-armour-stand-ticking.patch +++ b/patches/server/0227-Allow-disabling-armour-stand-ticking.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow disabling armour stand ticking diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 1cf6eb1b578561dfd9e734843fb87e477c7bde9e..d1b2b8c339449d57890fda5a8ff43786bbdd227d 100644 +index 6f0d3af10905161d9359d67ac17ce32da923d447..ff194e8c43ba576b2dc812bae7b1ae145115bf5e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -414,4 +414,10 @@ public class PaperWorldConfig { +@@ -419,4 +419,10 @@ public class PaperWorldConfig { private void armorStandEntityLookups() { armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true); } diff --git a/patches/server/0245-Configurable-speed-for-water-flowing-over-lava.patch b/patches/server/0245-Configurable-speed-for-water-flowing-over-lava.patch index abb7ec8937..ce3d7f6c74 100644 --- a/patches/server/0245-Configurable-speed-for-water-flowing-over-lava.patch +++ b/patches/server/0245-Configurable-speed-for-water-flowing-over-lava.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable speed for water flowing over lava diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index d1b2b8c339449d57890fda5a8ff43786bbdd227d..8c50036896602ab6b00979351918878d08c9c75e 100644 +index ff194e8c43ba576b2dc812bae7b1ae145115bf5e..dcd64f7d4b3ad4265d82ae82fb0014ab75939161 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -420,4 +420,10 @@ public class PaperWorldConfig { +@@ -425,4 +425,10 @@ public class PaperWorldConfig { this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); } diff --git a/patches/server/0276-Add-option-to-prevent-players-from-moving-into-unloa.patch b/patches/server/0276-Add-option-to-prevent-players-from-moving-into-unloa.patch index ba46c43241..ef379e6603 100644 --- a/patches/server/0276-Add-option-to-prevent-players-from-moving-into-unloa.patch +++ b/patches/server/0276-Add-option-to-prevent-players-from-moving-into-unloa.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add option to prevent players from moving into unloaded diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 8c50036896602ab6b00979351918878d08c9c75e..a4b20f8616b6fe2046e7a5f00306565b59cd570d 100644 +index dcd64f7d4b3ad4265d82ae82fb0014ab75939161..881cd17e2e9b54683941d58820b8bf0baf043f03 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -426,4 +426,9 @@ public class PaperWorldConfig { +@@ -431,4 +431,9 @@ public class PaperWorldConfig { waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5); log("Water over lava flow speed: " + waterOverLavaFlowSpeed); } diff --git a/patches/server/0322-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0322-Configurable-Keep-Spawn-Loaded-range-per-world.patch index df2ccec395..535f54b53e 100644 --- a/patches/server/0322-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0322-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Configurable Keep Spawn Loaded range per world This lets you disable it for some worlds and lower it for others. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a4b20f8616b6fe2046e7a5f00306565b59cd570d..47c8ea0e871959c01371f591c92d7955c0722878 100644 +index 881cd17e2e9b54683941d58820b8bf0baf043f03..bf85efd8ebfafe567c06b54425b9968daab6b2b1 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -56,6 +56,12 @@ public class PaperWorldConfig { +@@ -61,6 +61,12 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0329-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch b/patches/server/0329-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch index 1cb6d02e6b..36a52d3475 100644 --- a/patches/server/0329-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch +++ b/patches/server/0329-Only-count-Natural-Spawned-mobs-towards-natural-spaw.patch @@ -17,10 +17,10 @@ This should fully solve all of the issues around it so that only natural influences natural spawns. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 47c8ea0e871959c01371f591c92d7955c0722878..5dd6889e56b54402251978c9f2cff82729e0f3b6 100644 +index bf85efd8ebfafe567c06b54425b9968daab6b2b1..a460aa0c7573e4e8251d902c4394b0580a3282f5 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -437,4 +437,15 @@ public class PaperWorldConfig { +@@ -442,4 +442,15 @@ public class PaperWorldConfig { private void preventMovingIntoUnloadedChunks() { preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); } diff --git a/patches/server/0330-Configurable-projectile-relative-velocity.patch b/patches/server/0330-Configurable-projectile-relative-velocity.patch index b5a5ea9023..e5fc7134aa 100644 --- a/patches/server/0330-Configurable-projectile-relative-velocity.patch +++ b/patches/server/0330-Configurable-projectile-relative-velocity.patch @@ -25,10 +25,10 @@ P3) Solutions for 1) and especially 2) might not be future-proof, while this server-internal fix makes this change future-proof. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5dd6889e56b54402251978c9f2cff82729e0f3b6..b59eb179c188382d13c342ff78bc76c30ade8335 100644 +index a460aa0c7573e4e8251d902c4394b0580a3282f5..c057be04a2663b6dc14c6b5bda98312a28e86e66 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -447,5 +447,10 @@ public class PaperWorldConfig { +@@ -452,5 +452,10 @@ public class PaperWorldConfig { log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); } } diff --git a/patches/server/0335-Add-option-to-disable-pillager-patrols.patch b/patches/server/0335-Add-option-to-disable-pillager-patrols.patch index 49e3130841..a57216e6ba 100644 --- a/patches/server/0335-Add-option-to-disable-pillager-patrols.patch +++ b/patches/server/0335-Add-option-to-disable-pillager-patrols.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to disable pillager patrols diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b59eb179c188382d13c342ff78bc76c30ade8335..9bc6dc4e6159aa0ccad3cd7bdb331a852c5978ae 100644 +index c057be04a2663b6dc14c6b5bda98312a28e86e66..711614ec2dc4d8db4be3d1270a26286c782d1d01 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -452,5 +452,10 @@ public class PaperWorldConfig { +@@ -457,5 +457,10 @@ public class PaperWorldConfig { private void disableRelativeProjectileVelocity() { disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); } diff --git a/patches/server/0337-Flat-bedrock-generator-settings.patch b/patches/server/0337-Flat-bedrock-generator-settings.patch index 30c87be52e..adc62c6817 100644 --- a/patches/server/0337-Flat-bedrock-generator-settings.patch +++ b/patches/server/0337-Flat-bedrock-generator-settings.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Flat bedrock generator settings Co-authored-by: Noah van der Aa diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9bc6dc4e6159aa0ccad3cd7bdb331a852c5978ae..b602e30a7e1b760704ab2b53b594e1ebc057db01 100644 +index 711614ec2dc4d8db4be3d1270a26286c782d1d01..b68d72aa17a7c5e6fefb068c99eb8d89cdf0626e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -457,5 +457,10 @@ public class PaperWorldConfig { +@@ -462,5 +462,10 @@ public class PaperWorldConfig { private void pillagerSettings() { disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); } diff --git a/patches/server/0339-MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/0339-MC-145656-Fix-Follow-Range-Initial-Target.patch index 902a1f2d5e..8accba4935 100644 --- a/patches/server/0339-MC-145656-Fix-Follow-Range-Initial-Target.patch +++ b/patches/server/0339-MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -5,10 +5,10 @@ Subject: [PATCH] MC-145656 Fix Follow Range Initial Target diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index b602e30a7e1b760704ab2b53b594e1ebc057db01..11c5c7c703cbf631097056dd00a18a0236fac806 100644 +index b68d72aa17a7c5e6fefb068c99eb8d89cdf0626e..433ec51768081e4d4a5836b8f27f581d9541f641 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -462,5 +462,10 @@ public class PaperWorldConfig { +@@ -467,5 +467,10 @@ public class PaperWorldConfig { private void generatorSettings() { generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", this.generateFlatBedrock); } diff --git a/patches/server/0340-Duplicate-UUID-Resolve-Option.patch b/patches/server/0340-Duplicate-UUID-Resolve-Option.patch index 9960332821..076ee95ba7 100644 --- a/patches/server/0340-Duplicate-UUID-Resolve-Option.patch +++ b/patches/server/0340-Duplicate-UUID-Resolve-Option.patch @@ -33,10 +33,10 @@ But for those who are ok with leaving this inconsistent behavior, you may use WA It is recommended you regenerate the entities, as these were legit entities, and deserve your love. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 11c5c7c703cbf631097056dd00a18a0236fac806..2f060bc6b108df0c4fb07758005a911d92c09057 100644 +index 433ec51768081e4d4a5836b8f27f581d9541f641..90dafb6056a6ca2f60a441e26f9ebfecf18f8ced 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -438,6 +438,45 @@ public class PaperWorldConfig { +@@ -443,6 +443,45 @@ public class PaperWorldConfig { preventMovingIntoUnloadedChunks = getBoolean("prevent-moving-into-unloaded-chunks", false); } diff --git a/patches/server/0341-Optimize-Hoppers.patch b/patches/server/0341-Optimize-Hoppers.patch index e4e4770a2e..310c1dd5f6 100644 --- a/patches/server/0341-Optimize-Hoppers.patch +++ b/patches/server/0341-Optimize-Hoppers.patch @@ -13,10 +13,10 @@ Subject: [PATCH] Optimize Hoppers * Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 2f060bc6b108df0c4fb07758005a911d92c09057..73d82e20d7353120a36815dc94be8c2253b2602d 100644 +index 90dafb6056a6ca2f60a441e26f9ebfecf18f8ced..34c933dcd7d7adf5c9e631f8b8f60ba4d4ab53ba 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -506,5 +506,17 @@ public class PaperWorldConfig { +@@ -511,5 +511,17 @@ public class PaperWorldConfig { private void entitiesTargetWithFollowRange() { entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); } diff --git a/patches/server/0353-Increase-Light-Queue-Size.patch b/patches/server/0353-Increase-Light-Queue-Size.patch index 0a9c51833b..3b2028a340 100644 --- a/patches/server/0353-Increase-Light-Queue-Size.patch +++ b/patches/server/0353-Increase-Light-Queue-Size.patch @@ -14,10 +14,10 @@ light engine on shutdown... The queue size only puts a cap on max loss, doesn't solve that problem. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 73d82e20d7353120a36815dc94be8c2253b2602d..6b88162d286bdabda0449d52b87457ac70f84d69 100644 +index 34c933dcd7d7adf5c9e631f8b8f60ba4d4ab53ba..763b54e0d35730186bab3fc69babd9b5f0af0cf4 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -518,5 +518,10 @@ public class PaperWorldConfig { +@@ -523,5 +523,10 @@ public class PaperWorldConfig { hoppersIgnoreOccludingBlocks = getBoolean("hopper.ignore-occluding-blocks", hoppersIgnoreOccludingBlocks); log("Hopper Ignore Container Entities inside Occluding Blocks: " + (hoppersIgnoreOccludingBlocks ? "enabled" : "disabled")); } diff --git a/patches/server/0355-Anti-Xray.patch b/patches/server/0355-Anti-Xray.patch index 5637925313..a08a205455 100644 --- a/patches/server/0355-Anti-Xray.patch +++ b/patches/server/0355-Anti-Xray.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Anti-Xray diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 6b88162d286bdabda0449d52b87457ac70f84d69..ed976e0582dee32ccf3aad49efb0dd773f5f9d80 100644 +index 763b54e0d35730186bab3fc69babd9b5f0af0cf4..0e5091b50b19cb2c0b491479321ac978f272c04c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -1,11 +1,13 @@ @@ -22,7 +22,7 @@ index 6b88162d286bdabda0449d52b87457ac70f84d69..ed976e0582dee32ccf3aad49efb0dd77 import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -523,5 +525,40 @@ public class PaperWorldConfig { +@@ -528,5 +530,40 @@ public class PaperWorldConfig { private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); } @@ -1597,7 +1597,7 @@ index f3c67a815c570beb14136905cbf5aa4046ee8394..f8f44cb6e823a0150f3abdab133f8ae2 } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ad8392124f12f54f4ed03887c805367403e51bb6..06bfac218c750e3eb8d8a0d52d36ab94ef35ccb1 100644 +index e9c8eb1ca3e39840b3791d814b66ad5b5919112f..a6e7a609344f693cd0f51cfc4b122f45e24d0050 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -2222,7 +2222,7 @@ public final class CraftServer implements Server { diff --git a/patches/server/0356-Implement-alternative-item-despawn-rate.patch b/patches/server/0356-Implement-alternative-item-despawn-rate.patch index f95e91881e..fb9338eb73 100644 --- a/patches/server/0356-Implement-alternative-item-despawn-rate.patch +++ b/patches/server/0356-Implement-alternative-item-despawn-rate.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Implement alternative item-despawn-rate Co-authored-by: Noah van der Aa diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ed976e0582dee32ccf3aad49efb0dd773f5f9d80..f41e292e78b2c6874ee9f0cb4336263581339ca6 100644 +index 0e5091b50b19cb2c0b491479321ac978f272c04c..91a36bf77095f6c0c0b15dbed941bc95b3fb3bfe 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -560,5 +560,74 @@ public class PaperWorldConfig { +@@ -565,5 +565,74 @@ public class PaperWorldConfig { Bukkit.getLogger().warning("You have enabled permission-based Anti-Xray checking - depending on your permission plugin, this may cause performance issues"); } } diff --git a/patches/server/0359-implement-optional-per-player-mob-spawns.patch b/patches/server/0359-implement-optional-per-player-mob-spawns.patch index cbd7c808ec..7f760e3a29 100644 --- a/patches/server/0359-implement-optional-per-player-mob-spawns.patch +++ b/patches/server/0359-implement-optional-per-player-mob-spawns.patch @@ -5,10 +5,10 @@ Subject: [PATCH] implement optional per player mob spawns diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index f41e292e78b2c6874ee9f0cb4336263581339ca6..75d3365fe37dc419138295d2d28f8dfe1153c6c4 100644 +index 91a36bf77095f6c0c0b15dbed941bc95b3fb3bfe..2c8feeb15c71277e2daebdba5597b7302f9d7eda 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -630,4 +630,12 @@ public class PaperWorldConfig { +@@ -635,4 +635,12 @@ public class PaperWorldConfig { log("Alternative item despawn rate of " + key.getPath() + ": " + altItemDespawnRateMap.get(key)); } } diff --git a/patches/server/0367-Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/0367-Add-option-to-nerf-pigmen-from-nether-portals.patch index 43ab0fe04d..5253573aeb 100644 --- a/patches/server/0367-Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/0367-Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to nerf pigmen from nether portals diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 575f277a5d38ade7d70c632712ea895cde3bfaae..bcc6dd9f175431e47b92f6ee85b6f86d09011ac6 100644 +index 2c8feeb15c71277e2daebdba5597b7302f9d7eda..90aad7af5c08968f921c8eba8bba7d677ac76584 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -521,6 +521,11 @@ public class PaperWorldConfig { +@@ -526,6 +526,11 @@ public class PaperWorldConfig { log("Hopper Ignore Container Entities inside Occluding Blocks: " + (hoppersIgnoreOccludingBlocks ? "enabled" : "disabled")); } diff --git a/patches/server/0371-Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/0371-Add-option-to-allow-iron-golems-to-spawn-in-air.patch index 9af21c4957..9d3b4d7024 100644 --- a/patches/server/0371-Add-option-to-allow-iron-golems-to-spawn-in-air.patch +++ b/patches/server/0371-Add-option-to-allow-iron-golems-to-spawn-in-air.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to allow iron golems to spawn in air diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bcc6dd9f175431e47b92f6ee85b6f86d09011ac6..8ff3719184484399ba1760b0f5e43e3ca961a028 100644 +index 90aad7af5c08968f921c8eba8bba7d677ac76584..78dfee9892f56adcbe7c5567a40dec6b4779d004 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -418,6 +418,11 @@ public class PaperWorldConfig { +@@ -423,6 +423,11 @@ public class PaperWorldConfig { scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true); } diff --git a/patches/server/0372-Configurable-chance-of-villager-zombie-infection.patch b/patches/server/0372-Configurable-chance-of-villager-zombie-infection.patch index aa6c5e78b3..8e079b9981 100644 --- a/patches/server/0372-Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/0372-Configurable-chance-of-villager-zombie-infection.patch @@ -8,10 +8,10 @@ This allows you to solve an issue in vanilla behavior where: * On normal difficulty they will have a 50% of getting infected or dying. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 8ff3719184484399ba1760b0f5e43e3ca961a028..3db1230c3abe8f4ba321146f8adbff7fadad9362 100644 +index 78dfee9892f56adcbe7c5567a40dec6b4779d004..8a78ae8481d0ede674eb9aa56b9c8d5de5f730e9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -531,6 +531,11 @@ public class PaperWorldConfig { +@@ -536,6 +536,11 @@ public class PaperWorldConfig { nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen); } @@ -24,7 +24,7 @@ index 8ff3719184484399ba1760b0f5e43e3ca961a028..3db1230c3abe8f4ba321146f8adbff7f private void lightQueueSize() { lightQueueSize = getInt("light-queue-size", lightQueueSize); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 996613d75f66d97c3bd5241ca1c1346b92ec06dd..0ca58915b6b2eaf6a9765ba75d3e0773690ea040 100644 +index 0760fcc3bde6b819ae526e2c66486b09a948d98b..f09e9ae8e976b0150c00995cd22e64feaefd27be 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -449,10 +449,13 @@ public class Zombie extends Monster { diff --git a/patches/server/0375-Add-tick-times-API-and-mspt-command.patch b/patches/server/0375-Add-tick-times-API-and-mspt-command.patch index bcbc78ba95..c9afad933f 100644 --- a/patches/server/0375-Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/0375-Add-tick-times-API-and-mspt-command.patch @@ -84,8 +84,8 @@ index 2e7c3fe697ac29807107152ecd916dfe21625f0a..3b0fa01342fba7e05f061d398f2f072f commands.put("paper", new PaperCommand("paper")); + commands.put("mspt", new MSPTCommand("mspt")); - version = getInt("config-version", 26); - set("config-version", 26); + version = getInt("config-version", 27); + set("config-version", 27); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 287014feb99c67083a959f2c09213d49ad5f743d..2e08855085a547151140bcb05dce9bc469d81ff6 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/patches/server/0378-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0378-Pillager-patrol-spawn-settings-and-per-player-option.patch index 07c5463208..d1df0bfd37 100644 --- a/patches/server/0378-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0378-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -10,10 +10,10 @@ When not per player it will use the Vanilla mechanic of one delay per world and the world age for the start day. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3db1230c3abe8f4ba321146f8adbff7fadad9362..feadef47940a1eab3ea79236a40ffd3deb2660b2 100644 +index 8a78ae8481d0ede674eb9aa56b9c8d5de5f730e9..45770f3511bc2ed3da31bda195e8043a0fe29702 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -500,8 +500,18 @@ public class PaperWorldConfig { +@@ -505,8 +505,18 @@ public class PaperWorldConfig { } public boolean disablePillagerPatrols = false; diff --git a/patches/server/0403-Add-phantom-creative-and-insomniac-controls.patch b/patches/server/0403-Add-phantom-creative-and-insomniac-controls.patch index b3ab98ea95..570feecc42 100644 --- a/patches/server/0403-Add-phantom-creative-and-insomniac-controls.patch +++ b/patches/server/0403-Add-phantom-creative-and-insomniac-controls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add phantom creative and insomniac controls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 844b71128d4a9a926a86797f42288c26deb013a5..a4e4fdb2085616dc1334cfa96aa751250ac35be7 100644 +index 45770f3511bc2ed3da31bda195e8043a0fe29702..c16233c8cabab2efca9846988c5c843aa9441133 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -663,4 +663,11 @@ public class PaperWorldConfig { +@@ -668,4 +668,11 @@ public class PaperWorldConfig { } perPlayerMobSpawns = getBoolean("per-player-mob-spawns", true); } diff --git a/patches/server/0415-Option-for-maximum-exp-value-when-merging-orbs.patch b/patches/server/0415-Option-for-maximum-exp-value-when-merging-orbs.patch index 305da0515c..abc364f948 100644 --- a/patches/server/0415-Option-for-maximum-exp-value-when-merging-orbs.patch +++ b/patches/server/0415-Option-for-maximum-exp-value-when-merging-orbs.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Option for maximum exp value when merging orbs diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a4e4fdb2085616dc1334cfa96aa751250ac35be7..3a5b6bdd20645c2afc788893dfa33511145deb6d 100644 +index c16233c8cabab2efca9846988c5c843aa9441133..fcd5d4e54f339b3435888a2e9842f64aec46170f 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -670,4 +670,10 @@ public class PaperWorldConfig { +@@ -675,4 +675,10 @@ public class PaperWorldConfig { phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); } diff --git a/patches/server/0430-Delay-Chunk-Unloads-based-on-Player-Movement.patch b/patches/server/0430-Delay-Chunk-Unloads-based-on-Player-Movement.patch index c2aa99dda8..e9e14adef9 100644 --- a/patches/server/0430-Delay-Chunk-Unloads-based-on-Player-Movement.patch +++ b/patches/server/0430-Delay-Chunk-Unloads-based-on-Player-Movement.patch @@ -17,10 +17,10 @@ This allows servers with smaller worlds who do less long distance exploring to s wasting cpu cycles on saving/unloading/reloading chunks repeatedly. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3a5b6bdd20645c2afc788893dfa33511145deb6d..fb3023ee557b9c851d613aae0da26a4277d0ecd4 100644 +index fcd5d4e54f339b3435888a2e9842f64aec46170f..634affda96921a5453f89ddcc72fc482b162a085 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -676,4 +676,13 @@ public class PaperWorldConfig { +@@ -681,4 +681,13 @@ public class PaperWorldConfig { expMergeMaxValue = getInt("experience-merge-max-value", -1); log("Experience Merge Max Value: " + expMergeMaxValue); } diff --git a/patches/server/0451-incremental-chunk-and-player-saving.patch b/patches/server/0451-incremental-chunk-and-player-saving.patch index f10e05562b..b75220d719 100644 --- a/patches/server/0451-incremental-chunk-and-player-saving.patch +++ b/patches/server/0451-incremental-chunk-and-player-saving.patch @@ -5,7 +5,7 @@ Subject: [PATCH] incremental chunk and player saving diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 56b6d8019f72d11e97d30e83467839d8fcb85674..d404105573f3cda57e8eb6cad70d248d4e5e1bdf 100644 +index c639557108ad9c59ccdd0b543b5507fbab1e0fa4..5e531f9fc67bd3092b39f1d3b46b9490319dd79a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java @@ -459,4 +459,14 @@ public class PaperConfig { @@ -24,10 +24,10 @@ index 56b6d8019f72d11e97d30e83467839d8fcb85674..d404105573f3cda57e8eb6cad70d248d + } } diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 64ceb8609891f59f4cf3b54844a25402bab32c26..213e9db18d1e0eede0e825797a3d3c15f2b2567f 100644 +index 634affda96921a5453f89ddcc72fc482b162a085..0167b3f0c3f52f540edc381e532d777b90279201 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -64,6 +64,21 @@ public class PaperWorldConfig { +@@ -69,6 +69,21 @@ public class PaperWorldConfig { log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); } diff --git a/patches/server/0488-Add-zombie-targets-turtle-egg-config.patch b/patches/server/0488-Add-zombie-targets-turtle-egg-config.patch index dc8b6e1811..b9b63d40d1 100644 --- a/patches/server/0488-Add-zombie-targets-turtle-egg-config.patch +++ b/patches/server/0488-Add-zombie-targets-turtle-egg-config.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add zombie targets turtle egg config diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 213e9db18d1e0eede0e825797a3d3c15f2b2567f..0eecbb10fd82787293a41c213917b8885137ccc4 100644 +index 0167b3f0c3f52f540edc381e532d777b90279201..d6976656f10707da25e4b4ce51893d2d1bf80f2e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -58,6 +58,11 @@ public class PaperWorldConfig { +@@ -63,6 +63,11 @@ public class PaperWorldConfig { } } @@ -21,7 +21,7 @@ index 213e9db18d1e0eede0e825797a3d3c15f2b2567f..0eecbb10fd82787293a41c213917b888 private void keepLoadedRange() { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 0ca58915b6b2eaf6a9765ba75d3e0773690ea040..7f779d724f8682cdfb777375f7e0af48f53708d3 100644 +index f09e9ae8e976b0150c00995cd22e64feaefd27be..5341f65436bb147c8aed5206c5e4515c7517bc2e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -106,7 +106,7 @@ public class Zombie extends Monster { diff --git a/patches/server/0490-Optimize-redstone-algorithm.patch b/patches/server/0490-Optimize-redstone-algorithm.patch index a0b21ad242..2c23fa9558 100644 --- a/patches/server/0490-Optimize-redstone-algorithm.patch +++ b/patches/server/0490-Optimize-redstone-algorithm.patch @@ -19,10 +19,10 @@ Aside from making the obvious class/function renames and obfhelpers I didn't nee Just added Bukkit's event system and took a few liberties with dead code and comment misspellings. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0eecbb10fd82787293a41c213917b8885137ccc4..5c6c590a859e6a96b392a1146c4cc41dc6004c4c 100644 +index d6976656f10707da25e4b4ce51893d2d1bf80f2e..cba7aaed24550eea874f4ae7c37b537548635c43 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -63,6 +63,16 @@ public class PaperWorldConfig { +@@ -68,6 +68,16 @@ public class PaperWorldConfig { zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); } diff --git a/patches/server/0521-Toggle-for-removing-existing-dragon.patch b/patches/server/0521-Toggle-for-removing-existing-dragon.patch index 3b83fc6f46..ace684f6b7 100644 --- a/patches/server/0521-Toggle-for-removing-existing-dragon.patch +++ b/patches/server/0521-Toggle-for-removing-existing-dragon.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Toggle for removing existing dragon diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5c6c590a859e6a96b392a1146c4cc41dc6004c4c..86cddde870f3ec45e3708aadc1f3e4b19cbaebcc 100644 +index cba7aaed24550eea874f4ae7c37b537548635c43..581c13c7d1c423ea6d2ead112c3fb6691b64bc00 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -73,6 +73,14 @@ public class PaperWorldConfig { +@@ -78,6 +78,14 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0527-Add-Wandering-Trader-spawn-rate-config-options.patch b/patches/server/0527-Add-Wandering-Trader-spawn-rate-config-options.patch index af46d7f8ea..a8a84e175f 100644 --- a/patches/server/0527-Add-Wandering-Trader-spawn-rate-config-options.patch +++ b/patches/server/0527-Add-Wandering-Trader-spawn-rate-config-options.patch @@ -11,10 +11,10 @@ in IWorldServerData are removed as they were only used in certain places, with h values used in other places. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 86cddde870f3ec45e3708aadc1f3e4b19cbaebcc..681985c8412562fedea841738656ce0b7391964a 100644 +index 581c13c7d1c423ea6d2ead112c3fb6691b64bc00..638a3a70e33d2d817fef07e9a3f7a309aeab1759 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -81,6 +81,19 @@ public class PaperWorldConfig { +@@ -86,6 +86,19 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0535-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0535-Climbing-should-not-bypass-cramming-gamerule.patch index 3d038e5dbd..f20e003cf7 100644 --- a/patches/server/0535-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0535-Climbing-should-not-bypass-cramming-gamerule.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Climbing should not bypass cramming gamerule diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 681985c8412562fedea841738656ce0b7391964a..657a199a78262442427b308e94344790b6fa55dd 100644 +index 638a3a70e33d2d817fef07e9a3f7a309aeab1759..e2337fa6feb024f9a8a3f5f809cf67113cd41404 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -94,6 +94,11 @@ public class PaperWorldConfig { +@@ -99,6 +99,11 @@ public class PaperWorldConfig { wanderingTraderSpawnChanceMax = getInt("wandering-trader.spawn-chance-max", wanderingTraderSpawnChanceMax); } diff --git a/patches/server/0538-Fix-curing-zombie-villager-discount-exploit.patch b/patches/server/0538-Fix-curing-zombie-villager-discount-exploit.patch index ae2a285eda..b3aba69079 100644 --- a/patches/server/0538-Fix-curing-zombie-villager-discount-exploit.patch +++ b/patches/server/0538-Fix-curing-zombie-villager-discount-exploit.patch @@ -8,10 +8,10 @@ and curing a villager on repeat by simply resetting the relevant part of the reputation when it is cured. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 657a199a78262442427b308e94344790b6fa55dd..bebc057d4b7ca0944532e0377d794d7fdb5aebc2 100644 +index e2337fa6feb024f9a8a3f5f809cf67113cd41404..19ef3c1272fb364355eaac1dcae3ec1f9cc22b44 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -99,6 +99,11 @@ public class PaperWorldConfig { +@@ -104,6 +104,11 @@ public class PaperWorldConfig { fixClimbingBypassingCrammingRule = getBoolean("fix-climbing-bypassing-cramming-rule", fixClimbingBypassingCrammingRule); } diff --git a/patches/server/0553-Allow-disabling-mob-spawner-spawn-egg-transformation.patch b/patches/server/0553-Allow-disabling-mob-spawner-spawn-egg-transformation.patch index 9785ce3d5e..6d12fd5c1e 100644 --- a/patches/server/0553-Allow-disabling-mob-spawner-spawn-egg-transformation.patch +++ b/patches/server/0553-Allow-disabling-mob-spawner-spawn-egg-transformation.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow disabling mob spawner spawn egg transformation diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bebc057d4b7ca0944532e0377d794d7fdb5aebc2..9cbff12cdfe7882d90c481496a6e8d96b7f19315 100644 +index 19ef3c1272fb364355eaac1dcae3ec1f9cc22b44..244a9958430497e5ba05acc06a11ef3073e5e85d 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -104,6 +104,11 @@ public class PaperWorldConfig { +@@ -109,6 +109,11 @@ public class PaperWorldConfig { fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); } diff --git a/patches/server/0563-Added-world-settings-for-mobs-picking-up-loot.patch b/patches/server/0563-Added-world-settings-for-mobs-picking-up-loot.patch index 643cc13eaf..a1fd110490 100644 --- a/patches/server/0563-Added-world-settings-for-mobs-picking-up-loot.patch +++ b/patches/server/0563-Added-world-settings-for-mobs-picking-up-loot.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Added world settings for mobs picking up loot diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 375c15f672cbc612e4ab967d3519697937e7860e..137e4a16c4013bbbd6fed4f09f076267b2f45707 100644 +index 244a9958430497e5ba05acc06a11ef3073e5e85d..034be6700da0a4f929e442714e267db00cc054dc 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -737,6 +737,14 @@ public class PaperWorldConfig { +@@ -742,6 +742,14 @@ public class PaperWorldConfig { phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); } diff --git a/patches/server/0567-Configurable-door-breaking-difficulty.patch b/patches/server/0567-Configurable-door-breaking-difficulty.patch index a17a550eaa..f7344c350e 100644 --- a/patches/server/0567-Configurable-door-breaking-difficulty.patch +++ b/patches/server/0567-Configurable-door-breaking-difficulty.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Configurable door breaking difficulty Co-authored-by: Doc diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 137e4a16c4013bbbd6fed4f09f076267b2f45707..b452f3c15725a84dfd6358932146d1965a8a86f3 100644 +index 034be6700da0a4f929e442714e267db00cc054dc..81b5b686b108f9f622d0487686348db8b15c0309 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -108,6 +108,27 @@ public class PaperWorldConfig { +@@ -113,6 +113,27 @@ public class PaperWorldConfig { private void disableMobSpawnerSpawnEggTransformation() { disableMobSpawnerSpawnEggTransformation = getBoolean("game-mechanics.disable-mob-spawner-spawn-egg-transformation", disableMobSpawnerSpawnEggTransformation); } diff --git a/patches/server/0575-Collision-option-for-requiring-a-player-participant.patch b/patches/server/0575-Collision-option-for-requiring-a-player-participant.patch index 0a8b7f3c6e..c84e098b3a 100644 --- a/patches/server/0575-Collision-option-for-requiring-a-player-participant.patch +++ b/patches/server/0575-Collision-option-for-requiring-a-player-participant.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Collision option for requiring a player participant diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 512720c6c13edcdae8f334ee584da8c4bca30c5f..ea5f021c4ce2274869d884b90aeaba35d4e2db84 100644 +index 81b5b686b108f9f622d0487686348db8b15c0309..a799b732715e029e1b7ecae4acd4e283600e107b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -81,6 +81,18 @@ public class PaperWorldConfig { +@@ -86,6 +86,18 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0579-Configurable-max-leash-distance.patch b/patches/server/0579-Configurable-max-leash-distance.patch index a02efb1a4e..c1c603978b 100644 --- a/patches/server/0579-Configurable-max-leash-distance.patch +++ b/patches/server/0579-Configurable-max-leash-distance.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable max leash distance diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 4d3625e1bf1acdfdf226f788209e6b35793d7153..86d90de48281b2cf5f09206dd994133992904560 100644 +index a799b732715e029e1b7ecae4acd4e283600e107b..a33bdad2d588268bb0e9e9a1de1eb004d60c26ef 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -303,6 +303,12 @@ public class PaperWorldConfig { +@@ -308,6 +308,12 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0582-Add-toggle-for-always-placing-the-dragon-egg.patch b/patches/server/0582-Add-toggle-for-always-placing-the-dragon-egg.patch index d1088a50aa..ff691a8a70 100644 --- a/patches/server/0582-Add-toggle-for-always-placing-the-dragon-egg.patch +++ b/patches/server/0582-Add-toggle-for-always-placing-the-dragon-egg.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add toggle for always placing the dragon egg diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 86d90de48281b2cf5f09206dd994133992904560..0f6c8e1781054efc35ab737ca3fb4ce433210581 100644 +index a33bdad2d588268bb0e9e9a1de1eb004d60c26ef..c5696fcac75cc6d9735faa55f99e25c51e3b7252 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -769,6 +769,11 @@ public class PaperWorldConfig { +@@ -774,6 +774,11 @@ public class PaperWorldConfig { perPlayerMobSpawns = getBoolean("per-player-mob-spawns", true); } diff --git a/patches/server/0588-added-option-to-disable-pathfinding-updates-on-block.patch b/patches/server/0588-added-option-to-disable-pathfinding-updates-on-block.patch index 428d3de82b..0ae3ed7cb4 100644 --- a/patches/server/0588-added-option-to-disable-pathfinding-updates-on-block.patch +++ b/patches/server/0588-added-option-to-disable-pathfinding-updates-on-block.patch @@ -5,10 +5,10 @@ Subject: [PATCH] added option to disable pathfinding updates on block changes diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0f6c8e1781054efc35ab737ca3fb4ce433210581..698b46b78dd167c01bbe1ab077046be008f9cde1 100644 +index c5696fcac75cc6d9735faa55f99e25c51e3b7252..37ffb33b75c0f2d028d9ba020cc1cd6e5d4ba95c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -774,6 +774,11 @@ public class PaperWorldConfig { +@@ -779,6 +779,11 @@ public class PaperWorldConfig { enderDragonsDeathAlwaysPlacesDragonEgg = getBoolean("ender-dragons-death-always-places-dragon-egg", enderDragonsDeathAlwaysPlacesDragonEgg); } diff --git a/patches/server/0607-Allow-using-signs-inside-spawn-protection.patch b/patches/server/0607-Allow-using-signs-inside-spawn-protection.patch index de8ad10d18..12e1a38330 100644 --- a/patches/server/0607-Allow-using-signs-inside-spawn-protection.patch +++ b/patches/server/0607-Allow-using-signs-inside-spawn-protection.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow using signs inside spawn protection diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 698b46b78dd167c01bbe1ab077046be008f9cde1..03468b1d7bbc3528c959368d89ccb3374a17788e 100644 +index 37ffb33b75c0f2d028d9ba020cc1cd6e5d4ba95c..eb8193f4cd4f9bbc768e676ed16ace95d5a4ca0c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -808,4 +808,9 @@ public class PaperWorldConfig { +@@ -813,4 +813,9 @@ public class PaperWorldConfig { delayChunkUnloadsBy *= 20; } } diff --git a/patches/server/0616-Entity-load-save-limit-per-chunk.patch b/patches/server/0616-Entity-load-save-limit-per-chunk.patch index 69a570fb64..d5c8323213 100644 --- a/patches/server/0616-Entity-load-save-limit-per-chunk.patch +++ b/patches/server/0616-Entity-load-save-limit-per-chunk.patch @@ -9,7 +9,7 @@ defaults are only included for certain entites, this allows setting limits for any entity type. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 03468b1d7bbc3528c959368d89ccb3374a17788e..5837fe5ad3a5f77fab81153155b4e6fd8303bbf0 100644 +index eb8193f4cd4f9bbc768e676ed16ace95d5a4ca0c..17e3a9dd06d652d95ccaad1767c134831ae19c11 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -8,6 +8,8 @@ import it.unimi.dsi.fastutil.objects.Reference2IntMap; @@ -21,7 +21,7 @@ index 03468b1d7bbc3528c959368d89ccb3374a17788e..5837fe5ad3a5f77fab81153155b4e6fd import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -142,6 +144,38 @@ public class PaperWorldConfig { +@@ -147,6 +149,38 @@ public class PaperWorldConfig { } } diff --git a/patches/server/0658-Limit-item-frame-cursors-on-maps.patch b/patches/server/0658-Limit-item-frame-cursors-on-maps.patch index b40b9663a6..50ce3b823b 100644 --- a/patches/server/0658-Limit-item-frame-cursors-on-maps.patch +++ b/patches/server/0658-Limit-item-frame-cursors-on-maps.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Limit item frame cursors on maps diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5837fe5ad3a5f77fab81153155b4e6fd8303bbf0..9b960f9bb3332f06d2c82be430961772846fbf61 100644 +index 17e3a9dd06d652d95ccaad1767c134831ae19c11..83e56dba01998b2b83405fc831ec80d7054bc158 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -847,4 +847,9 @@ public class PaperWorldConfig { +@@ -852,4 +852,9 @@ public class PaperWorldConfig { private void allowUsingSignsInsideSpawnProtection() { allowUsingSignsInsideSpawnProtection = getBoolean("allow-using-signs-inside-spawn-protection", allowUsingSignsInsideSpawnProtection); } diff --git a/patches/server/0663-Add-option-to-fix-items-merging-through-walls.patch b/patches/server/0663-Add-option-to-fix-items-merging-through-walls.patch index cc1754d308..f6c4e1dbdd 100644 --- a/patches/server/0663-Add-option-to-fix-items-merging-through-walls.patch +++ b/patches/server/0663-Add-option-to-fix-items-merging-through-walls.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add option to fix items merging through walls diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 9b960f9bb3332f06d2c82be430961772846fbf61..0b76862934d679673d58b193df00ab4870b08d35 100644 +index 83e56dba01998b2b83405fc831ec80d7054bc158..2c4a34f10db9a2297815bad943a1145022abbb4b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -852,4 +852,9 @@ public class PaperWorldConfig { +@@ -857,4 +857,9 @@ public class PaperWorldConfig { private void mapItemFrameCursorLimit() { mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); } diff --git a/patches/server/0665-Fix-invulnerable-end-crystals.patch b/patches/server/0665-Fix-invulnerable-end-crystals.patch index c8bc68b8d2..fe8bac5939 100644 --- a/patches/server/0665-Fix-invulnerable-end-crystals.patch +++ b/patches/server/0665-Fix-invulnerable-end-crystals.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix invulnerable end crystals MC-108513 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0b76862934d679673d58b193df00ab4870b08d35..5015a49861bf6dfe32ba86415f22a7b3fd13aa9b 100644 +index 2c4a34f10db9a2297815bad943a1145022abbb4b..249da1eed197151926c30e64b11cbe49406bdbb0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -857,4 +857,9 @@ public class PaperWorldConfig { +@@ -862,4 +862,9 @@ public class PaperWorldConfig { private void fixItemsMergingThroughWalls() { fixItemsMergingThroughWalls = getBoolean("fix-items-merging-through-walls", fixItemsMergingThroughWalls); } diff --git a/patches/server/0671-add-per-world-spawn-limits.patch b/patches/server/0671-add-per-world-spawn-limits.patch index aa1344bd75..a472fea146 100644 --- a/patches/server/0671-add-per-world-spawn-limits.patch +++ b/patches/server/0671-add-per-world-spawn-limits.patch @@ -6,10 +6,10 @@ Subject: [PATCH] add per world spawn limits Taken from #2982. Credit to Chasewhip8 diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5015a49861bf6dfe32ba86415f22a7b3fd13aa9b..bf0ee7904c6c58a2bc44279be03fdf28abbabbc2 100644 +index 249da1eed197151926c30e64b11cbe49406bdbb0..d0b17ef93a7f0f1e6171550659532296f44a0306 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -53,6 +53,11 @@ public class PaperWorldConfig { +@@ -58,6 +58,11 @@ public class PaperWorldConfig { set("despawn-ranges.soft", null); set("despawn-ranges.hard", null); @@ -21,7 +21,7 @@ index 5015a49861bf6dfe32ba86415f22a7b3fd13aa9b..bf0ee7904c6c58a2bc44279be03fdf28 } if (needsSave) { -@@ -685,6 +690,21 @@ public class PaperWorldConfig { +@@ -690,6 +695,21 @@ public class PaperWorldConfig { zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); } diff --git a/patches/server/0679-Fix-commands-from-signs-not-firing-command-events.patch b/patches/server/0679-Fix-commands-from-signs-not-firing-command-events.patch index f2d12f7c91..c45ff7696e 100644 --- a/patches/server/0679-Fix-commands-from-signs-not-firing-command-events.patch +++ b/patches/server/0679-Fix-commands-from-signs-not-firing-command-events.patch @@ -10,10 +10,10 @@ This patch changes sign command logic so that `run_command` click events: - sends failure messages to the player who clicked the sign diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index bf0ee7904c6c58a2bc44279be03fdf28abbabbc2..3c56c37bcbfcad72cf9aa099eb9d5d3c40164c2e 100644 +index d0b17ef93a7f0f1e6171550659532296f44a0306..3d964f3bf92c2bcdb4c7abd02c5d172e27a3d49c 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -882,4 +882,9 @@ public class PaperWorldConfig { +@@ -887,4 +887,9 @@ public class PaperWorldConfig { private void fixInvulnerableEndCrystalExploit() { fixInvulnerableEndCrystalExploit = getBoolean("unsupported-settings.fix-invulnerable-end-crystal-exploit", fixInvulnerableEndCrystalExploit); } diff --git a/patches/server/0682-Add-config-for-mobs-immune-to-default-effects.patch b/patches/server/0682-Add-config-for-mobs-immune-to-default-effects.patch index c23fc59f8a..8f0590aa46 100644 --- a/patches/server/0682-Add-config-for-mobs-immune-to-default-effects.patch +++ b/patches/server/0682-Add-config-for-mobs-immune-to-default-effects.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add config for mobs immune to default effects diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 3c56c37bcbfcad72cf9aa099eb9d5d3c40164c2e..7bfbecb18241adcca49b9d70a903a8b7d1e65bfa 100644 +index 3d964f3bf92c2bcdb4c7abd02c5d172e27a3d49c..eab7759ecdfe436aa86d587530508fac2ad6064e 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -680,6 +680,21 @@ public class PaperWorldConfig { +@@ -685,6 +685,21 @@ public class PaperWorldConfig { log("Hopper Ignore Container Entities inside Occluding Blocks: " + (hoppersIgnoreOccludingBlocks ? "enabled" : "disabled")); } diff --git a/patches/server/0684-Don-t-apply-cramming-damage-to-players.patch b/patches/server/0684-Don-t-apply-cramming-damage-to-players.patch index f3bd2f47af..bf67d2b139 100644 --- a/patches/server/0684-Don-t-apply-cramming-damage-to-players.patch +++ b/patches/server/0684-Don-t-apply-cramming-damage-to-players.patch @@ -11,10 +11,10 @@ It does not make a lot of sense to damage players if they get crammed, For those who really want it a config option is provided. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 7bfbecb18241adcca49b9d70a903a8b7d1e65bfa..a4a1503624ceb2fd07614d10e1bf45b469e311e1 100644 +index eab7759ecdfe436aa86d587530508fac2ad6064e..09f2e29db50bdd77458a1ed884c22139141542e0 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -902,4 +902,9 @@ public class PaperWorldConfig { +@@ -907,4 +907,9 @@ public class PaperWorldConfig { private void showSignClickCommandFailureMessagesToPlayer() { showSignClickCommandFailureMessagesToPlayer = getBoolean("show-sign-click-command-failure-msgs-to-player", showSignClickCommandFailureMessagesToPlayer); } diff --git a/patches/server/0685-Rate-options-and-timings-for-sensors-and-behaviors.patch b/patches/server/0685-Rate-options-and-timings-for-sensors-and-behaviors.patch index 82b3bc02bf..64a1e652b4 100644 --- a/patches/server/0685-Rate-options-and-timings-for-sensors-and-behaviors.patch +++ b/patches/server/0685-Rate-options-and-timings-for-sensors-and-behaviors.patch @@ -28,7 +28,7 @@ index b47b7dce26805badd422c1867733ff4bfd00e9f4..b27021a42cbed3f0648a8d0903d00d03 * Get a named timer for the specified tile entity type to track type specific timings. * @param entity diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a4a1503624ceb2fd07614d10e1bf45b469e311e1..2bc1ff0c1bd659894766f47c014c8e708a0a2521 100644 +index 09f2e29db50bdd77458a1ed884c22139141542e0..cb5223be0721c599f9940be0c46caa48032f51b8 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -9,8 +9,10 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; @@ -42,7 +42,7 @@ index a4a1503624ceb2fd07614d10e1bf45b469e311e1..2bc1ff0c1bd659894766f47c014c8e70 import org.bukkit.configuration.file.YamlConfiguration; import org.spigotmc.SpigotWorldConfig; -@@ -907,4 +909,57 @@ public class PaperWorldConfig { +@@ -912,4 +914,57 @@ public class PaperWorldConfig { private void playerCrammingDamage() { allowPlayerCrammingDamage = getBoolean("allow-player-cramming-damage", allowPlayerCrammingDamage); } diff --git a/patches/server/0698-Config-option-for-Piglins-guarding-chests.patch b/patches/server/0698-Config-option-for-Piglins-guarding-chests.patch index ca40719e13..0a270e9832 100644 --- a/patches/server/0698-Config-option-for-Piglins-guarding-chests.patch +++ b/patches/server/0698-Config-option-for-Piglins-guarding-chests.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Config option for Piglins guarding chests diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5ad05615e4dc1cc14112ab40e435a72672eedb87..81d47e800b1dc1ae944b12313a8241c1d877e6a4 100644 +index cb5223be0721c599f9940be0c46caa48032f51b8..0564396dd3b47087f18f40a6896cdfb54cae3c7b 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -72,6 +72,11 @@ public class PaperWorldConfig { +@@ -77,6 +77,11 @@ public class PaperWorldConfig { zombiesTargetTurtleEggs = getBoolean("zombies-target-turtle-eggs", zombiesTargetTurtleEggs); } diff --git a/patches/server/0702-Configurable-item-frame-map-cursor-update-interval.patch b/patches/server/0702-Configurable-item-frame-map-cursor-update-interval.patch index a424ebc95e..f623f82624 100644 --- a/patches/server/0702-Configurable-item-frame-map-cursor-update-interval.patch +++ b/patches/server/0702-Configurable-item-frame-map-cursor-update-interval.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable item frame map cursor update interval diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 72d47018289f4174bf8655f15dce67490d36e05b..5ad6c46a5df9c4687a192198a8702d937a968ec8 100644 +index 0564396dd3b47087f18f40a6896cdfb54cae3c7b..998ae8b2e30d08e051a04a7649e5f5a416831166 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -895,6 +895,11 @@ public class PaperWorldConfig { +@@ -900,6 +900,11 @@ public class PaperWorldConfig { mapItemFrameCursorLimit = getInt("map-item-frame-cursor-limit", mapItemFrameCursorLimit); } diff --git a/patches/server/0784-Preserve-overstacked-loot.patch b/patches/server/0784-Preserve-overstacked-loot.patch index 8bdd005f37..f38976bb0b 100644 --- a/patches/server/0784-Preserve-overstacked-loot.patch +++ b/patches/server/0784-Preserve-overstacked-loot.patch @@ -10,10 +10,10 @@ chunk bans via the large amount of NBT created by unstacking the items. Fixes GH-5140 and GH-4748. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 5ad6c46a5df9c4687a192198a8702d937a968ec8..a17f4bd04d3e6b4eead0d1213c16db4648ba8715 100644 +index 998ae8b2e30d08e051a04a7649e5f5a416831166..01dda989e42da8dd3b76221e9fa2756f78803969 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -920,6 +920,11 @@ public class PaperWorldConfig { +@@ -925,6 +925,11 @@ public class PaperWorldConfig { allowPlayerCrammingDamage = getBoolean("allow-player-cramming-damage", allowPlayerCrammingDamage); } diff --git a/patches/server/0791-Configurable-feature-seeds.patch b/patches/server/0791-Configurable-feature-seeds.patch index db577ed077..a812fa656f 100644 --- a/patches/server/0791-Configurable-feature-seeds.patch +++ b/patches/server/0791-Configurable-feature-seeds.patch @@ -19,10 +19,10 @@ index ee72086b2dee2bd6415803e77825b2b1cb83cd3d..309dbf5fce3ce940d5e1b57d267b9d6b } final Object val = config.get(key); diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a17f4bd04d3e6b4eead0d1213c16db4648ba8715..ef754b706fff197075c09008496afd162642ad60 100644 +index 01dda989e42da8dd3b76221e9fa2756f78803969..1c805adcdb9f38d3181bb734228cf6b0b1e290a8 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -965,6 +965,55 @@ public class PaperWorldConfig { +@@ -970,6 +970,55 @@ public class PaperWorldConfig { return table; } diff --git a/patches/server/0802-Hide-unnecessary-itemmeta-from-clients.patch b/patches/server/0802-Hide-unnecessary-itemmeta-from-clients.patch index 5bacab54ca..d88fb62bea 100644 --- a/patches/server/0802-Hide-unnecessary-itemmeta-from-clients.patch +++ b/patches/server/0802-Hide-unnecessary-itemmeta-from-clients.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Hide unnecessary itemmeta from clients diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index ef754b706fff197075c09008496afd162642ad60..aa265bb42daa42e23d3935fa8f81052c1504ef3c 100644 +index 1c805adcdb9f38d3181bb734228cf6b0b1e290a8..11726f1f5ff82fc863fe9597de062fdeb2b313c9 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -935,6 +935,13 @@ public class PaperWorldConfig { +@@ -940,6 +940,13 @@ public class PaperWorldConfig { behaviorTickRates = loadTickRates("behavior"); } diff --git a/patches/server/0823-Configurable-max-block-light-for-monster-spawning.patch b/patches/server/0823-Configurable-max-block-light-for-monster-spawning.patch index 22e9f1ed04..e4f763e82c 100644 --- a/patches/server/0823-Configurable-max-block-light-for-monster-spawning.patch +++ b/patches/server/0823-Configurable-max-block-light-for-monster-spawning.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable max block light for monster spawning diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index aa265bb42daa42e23d3935fa8f81052c1504ef3c..fd584cdfc5ba9dec9806ab50e602a03a58f5c4f7 100644 +index 11726f1f5ff82fc863fe9597de062fdeb2b313c9..4448a1348a2483a57762f851cae2a17e516f63be 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -1033,4 +1033,9 @@ public class PaperWorldConfig { +@@ -1038,4 +1038,9 @@ public class PaperWorldConfig { Integer rate = table.get(columnKey, rowKey); return rate != null && rate > -1 ? rate : def; } diff --git a/patches/server/0832-Make-water-animal-spawn-height-configurable.patch b/patches/server/0832-Make-water-animal-spawn-height-configurable.patch index 2666cdf9e8..1b1c04d7b1 100644 --- a/patches/server/0832-Make-water-animal-spawn-height-configurable.patch +++ b/patches/server/0832-Make-water-animal-spawn-height-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make water animal spawn height configurable diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index fd584cdfc5ba9dec9806ab50e602a03a58f5c4f7..8430f99895021db64cbed7671c1d9c56021c31e1 100644 +index 4448a1348a2483a57762f851cae2a17e516f63be..43091d7f4a5b228b3b0cb586e4267f9bfff938af 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -387,6 +387,24 @@ public class PaperWorldConfig { +@@ -392,6 +392,24 @@ public class PaperWorldConfig { mobSpawnerTickRate = getInt("mob-spawner-tick-rate", 1); } diff --git a/patches/server/0838-Add-configurable-height-for-slime-spawn.patch b/patches/server/0838-Add-configurable-height-for-slime-spawn.patch index 2823bac706..a3f8b09869 100644 --- a/patches/server/0838-Add-configurable-height-for-slime-spawn.patch +++ b/patches/server/0838-Add-configurable-height-for-slime-spawn.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add configurable height for slime spawn diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 8430f99895021db64cbed7671c1d9c56021c31e1..4598c54007a90e9ebf9294f3e99c9f340c4b4fe8 100644 +index 43091d7f4a5b228b3b0cb586e4267f9bfff938af..2d87ebd657db2977b95c2f5707a36a313444b6e4 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -425,6 +425,16 @@ public class PaperWorldConfig { +@@ -430,6 +430,16 @@ public class PaperWorldConfig { allChunksAreSlimeChunks = getBoolean("all-chunks-are-slime-chunks", false); } diff --git a/patches/server/0905-Add-Alternate-Current-redstone-implementation.patch b/patches/server/0905-Add-Alternate-Current-redstone-implementation.patch new file mode 100644 index 0000000000..c5bb613429 --- /dev/null +++ b/patches/server/0905-Add-Alternate-Current-redstone-implementation.patch @@ -0,0 +1,2414 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Space Walker +Date: Tue, 5 Apr 2022 01:01:13 +0200 +Subject: [PATCH] Add Alternate Current redstone implementation + +Author: Space Walker + +Original license: MIT +Original project: https://github.com/SpaceWalkerRS/alternate-current + +This patch adds Alternate Current's redstone implementation as an alternative to vanilla and Eigencraft's. +Performance of (de)powering redstone dust is many times faster than vanilla, and even exceeds Eigencraft. +Similar to Eigencraft, Alternate Current heavily changes the update order of redstone dust. This means any contraption that +is location dependent in vanilla will either work everywhere or nowhere when using Alternate Current/Eigencraft. Beyond that +parity issues should be rare for both implementations, though Alternate Current has not been tested as thoroughly, so I +cannot comment on how the two compare in that aspect. + +Alternate Current is more invasive than Eigencraft, though some of the modifications can be removed with only a minor +performance penalty in a small number of cases. Alternate Current needs the following modifications: +* Level/ServerLevel: Each level has its own 'wire handler' that handles redstone dust power changes. +* RedStoneWireBlock: Replace calls to vanilla's or Eigencraft's methods for handling power changes with calls to +Alternate Current's wire handler. +* (optional) Every power emitter's block class: new methods added to these classes make it easier for Alternate Current +to check if any block is a potential power source. + +The use-faster-eigencraft-redstone config has been replaced with the redstone-implementation config, which can be used to +switch between the vanilla, Eigencraft, and Alternate Current implementations. + +diff --git a/src/main/java/alternate/current/wire/LevelHelper.java b/src/main/java/alternate/current/wire/LevelHelper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..186e0a86ceaed007d394378157ce1596a0601908 +--- /dev/null ++++ b/src/main/java/alternate/current/wire/LevelHelper.java +@@ -0,0 +1,64 @@ ++package alternate.current.wire; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.chunk.ChunkAccess; ++import net.minecraft.world.level.chunk.ChunkStatus; ++import net.minecraft.world.level.chunk.LevelChunkSection; ++ ++import org.bukkit.event.block.BlockRedstoneEvent; ++ ++public class LevelHelper { ++ ++ static int doRedstoneEvent(ServerLevel level, BlockPos pos, int prevPower, int newPower) { ++ BlockRedstoneEvent event = new BlockRedstoneEvent(level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), prevPower, newPower); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ return event.getNewCurrent(); ++ } ++ ++ /** ++ * An optimized version of Level.setBlock. Since this method is only used to ++ * update redstone wire block states, lighting checks, height map updates, and ++ * block entity updates are omitted. ++ */ ++ static boolean setWireState(ServerLevel level, BlockPos pos, BlockState state, boolean updateNeighborShapes) { ++ int y = pos.getY(); ++ ++ if (y < level.getMinBuildHeight() || y >= level.getMaxBuildHeight()) { ++ return false; ++ } ++ ++ int x = pos.getX(); ++ int z = pos.getZ(); ++ int index = level.getSectionIndex(y); ++ ++ ChunkAccess chunk = level.getChunk(x >> 4, z >> 4, ChunkStatus.FULL, true); ++ LevelChunkSection section = chunk.getSections()[index]; ++ ++ if (section == null) { ++ return false; // we should never get here ++ } ++ ++ BlockState prevState = section.setBlockState(x & 15, y & 15, z & 15, state); ++ ++ if (state == prevState) { ++ return false; ++ } ++ ++ // notify clients of the BlockState change ++ level.getChunkSource().blockChanged(pos); ++ // mark the chunk for saving ++ chunk.setUnsaved(true); ++ ++ if (updateNeighborShapes) { ++ prevState.updateIndirectNeighbourShapes(level, pos, Block.UPDATE_CLIENTS); ++ state.updateNeighbourShapes(level, pos, Block.UPDATE_CLIENTS); ++ state.updateIndirectNeighbourShapes(level, pos, Block.UPDATE_CLIENTS); ++ } ++ ++ return true; ++ } ++} +diff --git a/src/main/java/alternate/current/wire/Node.java b/src/main/java/alternate/current/wire/Node.java +new file mode 100644 +index 0000000000000000000000000000000000000000..acfe97d62ef863a14e2e43db30917bd57bbd5171 +--- /dev/null ++++ b/src/main/java/alternate/current/wire/Node.java +@@ -0,0 +1,97 @@ ++package alternate.current.wire; ++ ++import java.util.Arrays; ++ ++import alternate.current.wire.WireHandler.Directions; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.BlockState; ++ ++/** ++ * A Node represents a block in the world. It also holds a few other pieces of ++ * information that speed up the calculations in the WireHandler class. ++ * ++ * @author Space Walker ++ */ ++public class Node { ++ ++ // flags that encode the Node type ++ private static final int CONDUCTOR = 0b01; ++ private static final int SOURCE = 0b10; ++ ++ final ServerLevel level; ++ final Node[] neighbors; ++ ++ BlockPos pos; ++ BlockState state; ++ boolean invalid; ++ ++ private int flags; ++ ++ Node(ServerLevel level) { ++ this.level = level; ++ this.neighbors = new Node[Directions.ALL.length]; ++ } ++ ++ @Override ++ public boolean equals(Object obj) { ++ if (this == obj) { ++ return true; ++ } ++ if (!(obj instanceof Node)) { ++ return false; ++ } ++ ++ Node node = (Node)obj; ++ ++ return level == node.level && pos.equals(node.pos); ++ } ++ ++ @Override ++ public int hashCode() { ++ return pos.hashCode(); ++ } ++ ++ Node update(BlockPos pos, BlockState state, boolean clearNeighbors) { ++ if (state.is(Blocks.REDSTONE_WIRE)) { ++ throw new IllegalStateException("Cannot update a regular Node to a WireNode!"); ++ } ++ ++ if (clearNeighbors) { ++ Arrays.fill(neighbors, null); ++ } ++ ++ this.pos = pos.immutable(); ++ this.state = state; ++ this.invalid = false; ++ ++ this.flags = 0; ++ ++ if (this.state.isRedstoneConductor(this.level, this.pos)) { ++ this.flags |= CONDUCTOR; ++ } ++ if (this.state.isSignalSource()) { ++ this.flags |= SOURCE; ++ } ++ ++ return this; ++ } ++ ++ public boolean isWire() { ++ return false; ++ } ++ ++ public boolean isConductor() { ++ return (flags & CONDUCTOR) != 0; ++ } ++ ++ public boolean isSignalSource() { ++ return (flags & SOURCE) != 0; ++ } ++ ++ public WireNode asWire() { ++ throw new UnsupportedOperationException("Not a WireNode!"); ++ } ++} +diff --git a/src/main/java/alternate/current/wire/PowerQueue.java b/src/main/java/alternate/current/wire/PowerQueue.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9c293bef09ad1c95ba24ea6c41a27c5489b548dd +--- /dev/null ++++ b/src/main/java/alternate/current/wire/PowerQueue.java +@@ -0,0 +1,209 @@ ++package alternate.current.wire; ++ ++import java.util.AbstractQueue; ++import java.util.Arrays; ++import java.util.Iterator; ++ ++import net.minecraft.world.level.redstone.Redstone; ++ ++public class PowerQueue extends AbstractQueue { ++ ++ private static final int OFFSET = -Redstone.SIGNAL_MIN; ++ ++ /** The last wire for each power level. */ ++ private final WireNode[] tails; ++ ++ private WireNode head; ++ private WireNode tail; ++ ++ private int size; ++ ++ public PowerQueue() { ++ this.tails = new WireNode[(Redstone.SIGNAL_MAX + 1) - Redstone.SIGNAL_MIN]; ++ } ++ ++ @Override ++ public boolean offer(WireNode wire) { ++ if (wire == null) { ++ throw new NullPointerException(); ++ } ++ ++ int power = wire.nextPower(); ++ ++ if (contains(wire)) { ++ if (wire.power == power) { ++ // already queued for this power; exit ++ return false; ++ } else { ++ // already queued for different power; move it ++ move(wire, power); ++ } ++ } else { ++ insert(wire, power); ++ } ++ ++ return true; ++ } ++ ++ @Override ++ public WireNode poll() { ++ if (head == null) { ++ return null; ++ } ++ ++ WireNode wire = head; ++ WireNode next = wire.next; ++ ++ if (next == null) { ++ clear(); // reset the tails array ++ } else { ++ if (wire.power != next.power) { ++ // if the head is also a tail, its entry in the array ++ // can be cleared; there is no previous wire with the ++ // same power to take its place. ++ tails[wire.power + OFFSET] = null; ++ } ++ ++ wire.next = null; ++ next.prev = null; ++ head = next; ++ ++ size--; ++ } ++ ++ return wire; ++ } ++ ++ @Override ++ public WireNode peek() { ++ return head; ++ } ++ ++ @Override ++ public void clear() { ++ for (WireNode wire = head; wire != null; ) { ++ WireNode w = wire; ++ wire = wire.next; ++ ++ w.prev = null; ++ w.next = null; ++ } ++ ++ head = null; ++ tail = null; ++ ++ Arrays.fill(tails, null); ++ ++ size = 0; ++ } ++ ++ @Override ++ public Iterator iterator() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public int size() { ++ return size; ++ } ++ ++ public boolean contains(WireNode wire) { ++ return wire == head || wire.prev != null; ++ } ++ ++ private void move(WireNode wire, int power) { ++ remove(wire); ++ insert(wire, power); ++ } ++ ++ private void remove(WireNode wire) { ++ if (wire == tail || wire.power != wire.next.power) { ++ // assign a new tail for this wire's power ++ if (wire == head || wire.power != wire.prev.power) { ++ // there is no other wire with the same power; clear ++ tails[wire.power + OFFSET] = null; ++ } else { ++ // the previous wire in the queue becomes the tail ++ tails[wire.power + OFFSET] = wire.prev; ++ } ++ } ++ ++ if (wire == head) { ++ head = wire.next; ++ } else { ++ wire.prev.next = wire.next; ++ } ++ if (wire == tail) { ++ tail = wire.prev; ++ } else { ++ wire.next.prev = wire.prev; ++ } ++ ++ wire.prev = null; ++ wire.next = null; ++ ++ size--; ++ } ++ ++ private void insert(WireNode wire, int power) { ++ // store the power for which this wire is queued ++ wire.power = power; ++ ++ // wires are sorted by power (highest to lowest) ++ // wires with the same power are ordered FIFO ++ if (head == null) { ++ // first element in this queue \o/ ++ head = tail = wire; ++ } else if (wire.power > head.power) { ++ linkHead(wire); ++ } else if (wire.power <= tail.power) { ++ linkTail(wire); ++ } else { ++ // since the wire is neither the head nor the tail ++ // findPrev is guaranteed to find a non-null element ++ linkAfter(findPrev(wire), wire); ++ } ++ ++ tails[power + OFFSET] = wire; ++ ++ size++; ++ } ++ ++ private void linkHead(WireNode wire) { ++ wire.next = head; ++ head.prev = wire; ++ head = wire; ++ } ++ ++ private void linkTail(WireNode wire) { ++ tail.next = wire; ++ wire.prev = tail; ++ tail = wire; ++ } ++ ++ private void linkAfter(WireNode prev, WireNode wire) { ++ linkBetween(prev, wire, prev.next); ++ } ++ ++ private void linkBetween(WireNode prev, WireNode wire, WireNode next) { ++ prev.next = wire; ++ wire.prev = prev; ++ ++ wire.next = next; ++ next.prev = wire; ++ } ++ ++ private WireNode findPrev(WireNode wire) { ++ WireNode prev = null; ++ ++ for (int i = wire.power + OFFSET; i < tails.length; i++) { ++ prev = tails[i]; ++ ++ if (prev != null) { ++ break; ++ } ++ } ++ ++ return prev; ++ } ++} +diff --git a/src/main/java/alternate/current/wire/WireConnection.java b/src/main/java/alternate/current/wire/WireConnection.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4fd8cb29024330397cfe4cbc1f237d285bfb7b3e +--- /dev/null ++++ b/src/main/java/alternate/current/wire/WireConnection.java +@@ -0,0 +1,30 @@ ++package alternate.current.wire; ++ ++/** ++ * This class represents a connection between some WireNode (the 'owner') and a ++ * neighboring WireNode. Two wires are considered to be connected if power can ++ * flow from one wire to the other (and/or vice versa). ++ * ++ * @author Space Walker ++ */ ++public class WireConnection { ++ ++ /** The connected wire. */ ++ final WireNode wire; ++ /** Cardinal direction to the connected wire. */ ++ final int iDir; ++ /** True if the owner of the connection can provide power to the connected wire. */ ++ final boolean offer; ++ /** True if the connected wire can provide power to the owner of the connection. */ ++ final boolean accept; ++ ++ /** The next connection in the sequence. */ ++ WireConnection next; ++ ++ WireConnection(WireNode wire, int iDir, boolean offer, boolean accept) { ++ this.wire = wire; ++ this.iDir = iDir; ++ this.offer = offer; ++ this.accept = accept; ++ } ++} +diff --git a/src/main/java/alternate/current/wire/WireConnectionManager.java b/src/main/java/alternate/current/wire/WireConnectionManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1dae7c0b896300ac9f0dd360dca23ca1de24dc66 +--- /dev/null ++++ b/src/main/java/alternate/current/wire/WireConnectionManager.java +@@ -0,0 +1,139 @@ ++package alternate.current.wire; ++ ++import java.util.Arrays; ++import java.util.function.Consumer; ++ ++import alternate.current.wire.WireHandler.Directions; ++import alternate.current.wire.WireHandler.NodeProvider; ++ ++public class WireConnectionManager { ++ ++ /** The owner of these connections. */ ++ final WireNode owner; ++ ++ /** The first connection for each cardinal direction. */ ++ private final WireConnection[] heads; ++ ++ private WireConnection head; ++ private WireConnection tail; ++ ++ /** The total number of connections. */ ++ int total; ++ ++ /** ++ * A 4 bit number that encodes in which direction(s) the owner has connections ++ * to other wires. ++ */ ++ private int flowTotal; ++ /** The direction of flow based connections to other wires. */ ++ int iFlowDir; ++ ++ WireConnectionManager(WireNode owner) { ++ this.owner = owner; ++ ++ this.heads = new WireConnection[Directions.HORIZONTAL.length]; ++ ++ this.total = 0; ++ ++ this.flowTotal = 0; ++ this.iFlowDir = -1; ++ } ++ ++ void set(NodeProvider nodes) { ++ if (total > 0) { ++ clear(); ++ } ++ ++ boolean belowIsConductor = nodes.getNeighbor(owner, Directions.DOWN).isConductor(); ++ boolean aboveIsConductor = nodes.getNeighbor(owner, Directions.UP).isConductor(); ++ ++ for (int iDir = 0; iDir < Directions.HORIZONTAL.length; iDir++) { ++ Node neighbor = nodes.getNeighbor(owner, iDir); ++ ++ if (neighbor.isWire()) { ++ add(neighbor.asWire(), iDir, true, true); ++ ++ continue; ++ } ++ ++ boolean sideIsConductor = neighbor.isConductor(); ++ ++ if (!sideIsConductor) { ++ Node node = nodes.getNeighbor(neighbor, Directions.DOWN); ++ ++ if (node.isWire()) { ++ add(node.asWire(), iDir, belowIsConductor, true); ++ } ++ } ++ if (!aboveIsConductor) { ++ Node node = nodes.getNeighbor(neighbor, Directions.UP); ++ ++ if (node.isWire()) { ++ add(node.asWire(), iDir, true, sideIsConductor); ++ } ++ } ++ } ++ ++ if (total > 0) { ++ iFlowDir = WireHandler.FLOW_IN_TO_FLOW_OUT[flowTotal]; ++ } ++ } ++ ++ private void clear() { ++ Arrays.fill(heads, null); ++ ++ head = null; ++ tail = null; ++ ++ total = 0; ++ ++ flowTotal = 0; ++ iFlowDir = -1; ++ } ++ ++ private void add(WireNode wire, int iDir, boolean offer, boolean accept) { ++ add(new WireConnection(wire, iDir, offer, accept)); ++ } ++ ++ private void add(WireConnection connection) { ++ if (head == null) { ++ head = connection; ++ tail = connection; ++ } else { ++ tail.next = connection; ++ tail = connection; ++ } ++ ++ if (heads[connection.iDir] == null) { ++ heads[connection.iDir] = connection; ++ ++ flowTotal |= (1 << connection.iDir); ++ } ++ ++ total++; ++ } ++ ++ /** ++ * Iterate over all connections, without any specific ++ * update order in mind. Use this method if the iteration ++ * order is not important. ++ */ ++ void forEach(Consumer consumer) { ++ for (WireConnection c = head; c != null; c = c.next) { ++ consumer.accept(c); ++ } ++ } ++ ++ /** ++ * Iterate over all connections in an order determined by ++ * the given flow direction. Use this method if the iteration ++ * order is important. ++ */ ++ void forEach(Consumer consumer, int iFlowDir) { ++ for (int iDir : WireHandler.CARDINAL_UPDATE_ORDERS[iFlowDir]) { ++ for (WireConnection c = heads[iDir]; c != null && c.iDir == iDir; c = c.next) { ++ consumer.accept(c); ++ } ++ } ++ } ++} +diff --git a/src/main/java/alternate/current/wire/WireHandler.java b/src/main/java/alternate/current/wire/WireHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ef84b462aa4a0cedbf7c3cfb54ba43f31b8f4e2f +--- /dev/null ++++ b/src/main/java/alternate/current/wire/WireHandler.java +@@ -0,0 +1,1106 @@ ++package alternate.current.wire; ++ ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Queue; ++ ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry; ++import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; ++import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.Direction; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.redstone.Redstone; ++ ++/** ++ * This class handles power changes for redstone wire. The algorithm was ++ * designed with the following goals in mind: ++ *
++ * 1. Minimize the number of times a wire checks its surroundings to determine ++ * its power level. ++ *
++ * 2. Minimize the number of block and shape updates emitted. ++ *
++ * 3. Emit block and shape updates in a deterministic, non-locational order, ++ * fixing bug MC-11193. ++ * ++ *

++ * In Vanilla redstone wire is laggy because it fails on points 1 and 2. ++ * ++ *

++ * Redstone wire updates recursively and each wire calculates its power level in ++ * isolation rather than in the context of the network it is a part of. This ++ * means a wire in a grid can change its power level over half a dozen times ++ * before settling on its final value. This problem used to be worse in 1.13 and ++ * below, where a wire would only decrease its power level by 1 at a time. ++ * ++ *

++ * In addition to this, a wire emits 42 block updates and up to 22 shape updates ++ * each time it changes its power level. ++ * ++ *

++ * Of those 42 block updates, 6 are to itself, which are thus not only ++ * redundant, but a big source of lag, since those cause the wire to ++ * unnecessarily re-calculate its power level. A block only has 24 neighbors ++ * within a Manhattan distance of 2, meaning 12 of the remaining 36 block ++ * updates are duplicates and thus also redundant. ++ * ++ *

++ * Of the 22 shape updates, only 6 are strictly necessary. The other 16 are sent ++ * to blocks diagonally above and below. These are necessary if a wire changes ++ * its connections, but not when it changes its power level. ++ * ++ *

++ * Redstone wire in Vanilla also fails on point 3, though this is more of a ++ * quality-of-life issue than a lag issue. The recursive nature in which it ++ * updates, combined with the location-dependent order in which each wire ++ * updates its neighbors, makes the order in which neighbors of a wire network ++ * are updated incredibly inconsistent and seemingly random. ++ * ++ *

++ * Alternate Current fixes each of these problems as follows. ++ * ++ *

++ * 1. To make sure a wire calculates its power level as little as possible, we ++ * remove the recursive nature in which redstone wire updates in Vanilla. ++ * Instead, we build a network of connected wires, find those wires that receive ++ * redstone power from "outside" the network, and spread the power from there. ++ * This has a few advantages: ++ *
++ * - Each wire checks for power from non-wire components just once, and from ++ * nearby wires just twice. ++ *
++ * - Each wire only sets its power level in the world once. This is important, ++ * because calls to Level.setBlock are even more expensive than calls to ++ * Level.getBlockState. ++ * ++ *

++ * 2. There are 2 obvious ways in which we can reduce the number of block and ++ * shape updates. ++ *
++ * - Get rid of the 18 redundant block updates and 16 redundant shape updates, ++ * so each wire only emits 24 block updates and 6 shape updates whenever it ++ * changes its power level. ++ *
++ * - Only emit block updates and shape updates once a wire reaches its final ++ * power level, rather than at each intermediary stage. ++ *
++ * For an individual wire, these two optimizations are the best you can do, but ++ * for an entire grid, you can do better! ++ * ++ *

++ * Since we calculate the power of the entire network, sending block and shape ++ * updates to the wires in it is redundant. Removing those updates can reduce ++ * the number of block and shape updates by up to 20%. ++ * ++ *

++ * 3. To make the order of block updates to neighbors of a network ++ * deterministic, the first thing we must do is to replace the location- ++ * dependent order in which a wire updates its neighbors. Instead, we base it on ++ * the direction of power flow. This part of the algorithm was heavily inspired ++ * by theosib's 'RedstoneWireTurbo', which you can read more about in theosib's ++ * comment on Mojira here ++ * or by checking out its implementation in carpet mod here. ++ * ++ *

++ * The idea is to determine the direction of power flow through a wire based on ++ * the power it receives from neighboring wires. For example, if the only power ++ * a wire receives is from a neighboring wire to its west, it can be said that ++ * the direction of power flow through the wire is east. ++ * ++ *

++ * We make the order of block updates to neighbors of a wire depend on what is ++ * determined to be the direction of power flow. This not only removes ++ * locationality entirely, it even removes directionality in a large number of ++ * cases. Unlike in 'RedstoneWireTurbo', however, I have decided to keep a ++ * directional element in ambiguous cases, rather than to introduce randomness, ++ * though this is trivial to change. ++ * ++ *

++ * While this change fixes the block update order of individual wires, we must ++ * still address the overall block update order of a network. This turns out to ++ * be a simple fix, because of a change we made earlier: we search through the ++ * network for wires that receive power from outside it, and spread the power ++ * from there. If we make each wire transmit its power to neighboring wires in ++ * an order dependent on the direction of power flow, we end up with a ++ * non-locational and largely non-directional wire update order. ++ * ++ * @author Space Walker ++ */ ++public class WireHandler { ++ ++ public static class Directions { ++ ++ public static final Direction[] ALL = { Direction.WEST, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.DOWN, Direction.UP }; ++ public static final Direction[] HORIZONTAL = { Direction.WEST, Direction.NORTH, Direction.EAST, Direction.SOUTH }; ++ ++ // Indices for the arrays above. ++ // The cardinal directions are ordered clockwise. This allows ++ // for conversion between relative and absolute directions ++ // ('left' 'right' vs 'east' 'west') with simple arithmetic: ++ // If some Direction index 'iDir' is considered 'forward', then ++ // '(iDir + 1) & 0b11' is 'right', '(iDir + 2) & 0b11' is 'backward', etc. ++ public static final int WEST = 0b000; // 0 ++ public static final int NORTH = 0b001; // 1 ++ public static final int EAST = 0b010; // 2 ++ public static final int SOUTH = 0b011; // 3 ++ public static final int DOWN = 0b100; // 4 ++ public static final int UP = 0b101; // 5 ++ ++ public static int iOpposite(int iDir) { ++ return iDir ^ (0b10 >>> (iDir >>> 2)); ++ } ++ ++ /** ++ * Each array is placed at the index that encodes the direction that is missing ++ * from the array. ++ */ ++ private static final int[][] I_EXCEPT = { ++ { NORTH, EAST, SOUTH, DOWN, UP }, ++ { WEST, EAST, SOUTH, DOWN, UP }, ++ { WEST, NORTH, SOUTH, DOWN, UP }, ++ { WEST, NORTH, EAST, DOWN, UP }, ++ { WEST, NORTH, EAST, SOUTH, UP }, ++ { WEST, NORTH, EAST, SOUTH, DOWN } ++ }; ++ } ++ ++ /** ++ * This conversion table takes in information about incoming flow, and outputs ++ * the determined outgoing flow. ++ * ++ *

++ * The input is a 4 bit number that encodes the incoming flow. Each bit ++ * represents a cardinal direction, and when it is 'on', there is flow in that ++ * direction. ++ * ++ *

++ * The output is a single Direction index, or -1 for ambiguous cases. ++ * ++ *

++ * The outgoing flow is determined as follows: ++ * ++ *

++ * If there is just 1 direction of incoming flow, that direction will be the ++ * direction of outgoing flow. ++ * ++ *

++ * If there are 2 directions of incoming flow, and these directions are not each ++ * other's opposites, the direction that is 'more clockwise' will be the ++ * direction of outgoing flow. More precisely, the direction that is 1 clockwise ++ * turn from the other is picked. ++ * ++ *

++ * If there are 3 directions of incoming flow, the two opposing directions ++ * cancel each other out, and the remaining direction will be the direction of ++ * outgoing flow. ++ * ++ *

++ * In all other cases, the flow is completely ambiguous. ++ */ ++ static final int[] FLOW_IN_TO_FLOW_OUT = { ++ -1, // 0b0000: - -> x ++ Directions.WEST, // 0b0001: west -> west ++ Directions.NORTH, // 0b0010: north -> north ++ Directions.NORTH, // 0b0011: west/north -> north ++ Directions.EAST, // 0b0100: east -> east ++ -1, // 0b0101: west/east -> x ++ Directions.EAST, // 0b0110: north/east -> east ++ Directions.NORTH, // 0b0111: west/north/east -> north ++ Directions.SOUTH, // 0b1000: south -> south ++ Directions.WEST, // 0b1001: west/south -> west ++ -1, // 0b1010: north/south -> x ++ Directions.WEST, // 0b1011: west/north/south -> west ++ Directions.SOUTH, // 0b1100: east/south -> south ++ Directions.SOUTH, // 0b1101: west/east/south -> south ++ Directions.EAST, // 0b1110: north/east/south -> east ++ -1, // 0b1111: west/north/east/south -> x ++ }; ++ /** ++ * Update order of cardinal directions. Given that the index encodes the ++ * direction that is to be considered 'forward', the resulting update order is { ++ * front, back, right, left }. ++ */ ++ static final int[][] CARDINAL_UPDATE_ORDERS = { ++ { Directions.WEST , Directions.EAST , Directions.NORTH, Directions.SOUTH }, ++ { Directions.NORTH, Directions.SOUTH, Directions.EAST , Directions.WEST }, ++ { Directions.EAST , Directions.WEST , Directions.SOUTH, Directions.NORTH }, ++ { Directions.SOUTH, Directions.NORTH, Directions.WEST , Directions.EAST } ++ }; ++ /** ++ * The default update order of all cardinal directions. ++ */ ++ static final int[] DEFAULT_CARDINAL_UPDATE_ORDER = CARDINAL_UPDATE_ORDERS[0]; ++ /** ++ * The default update order of all directions. It is equivalent to the order of ++ * shape updates in vanilla Minecraft. ++ */ ++ static final int[] DEFAULT_FULL_UPDATE_ORDER = { ++ Directions.WEST, ++ Directions.EAST, ++ Directions.NORTH, ++ Directions.SOUTH, ++ Directions.DOWN, ++ Directions.UP ++ }; ++ ++ // If Vanilla will ever multi-thread the ticking of levels, there should ++ // be only one WireHandler per level, in case redstone updates in multiple ++ // levels at the same time. There are already mods that add multi-threading ++ // as well. ++ private final ServerLevel level; ++ ++ /** All the wires in the network. */ ++ private final List network; ++ /** Map of wires and neighboring blocks. */ ++ private final Long2ObjectMap nodes; ++ /** All the power changes that need to happen. */ ++ private final Queue powerChanges; ++ ++ private int rootCount; ++ // Rather than creating new nodes every time a network is updated we keep ++ // a cache of nodes that can be re-used. ++ private Node[] nodeCache; ++ private int nodeCount; ++ ++ private boolean updatingPower; ++ ++ public WireHandler(ServerLevel level) { ++ this.level = level; ++ ++ this.network = new ArrayList<>(); ++ this.nodes = new Long2ObjectOpenHashMap<>(); ++ this.powerChanges = new PowerQueue(); ++ ++ this.nodeCache = new Node[16]; ++ this.fillNodeCache(0, 16); ++ } ++ ++ private Node getOrAddNode(BlockPos pos) { ++ return nodes.compute(pos.asLong(), (key, node) -> { ++ if (node == null) { ++ // If there is not yet a node at this position, retrieve and ++ // update one from the cache. ++ return getNextNode(pos); ++ } ++ if (node.invalid) { ++ return revalidateNode(node); ++ } ++ ++ return node; ++ }); ++ } ++ ++ /** ++ * Retrieve the neighbor of a node in the given direction and create a link ++ * between the two nodes. ++ */ ++ private Node getNeighbor(Node node, int iDir) { ++ Node neighbor = node.neighbors[iDir]; ++ ++ if (neighbor == null || neighbor.invalid) { ++ Direction dir = Directions.ALL[iDir]; ++ BlockPos pos = node.pos.relative(dir); ++ ++ Node oldNeighbor = neighbor; ++ neighbor = getOrAddNode(pos); ++ ++ if (neighbor != oldNeighbor) { ++ int iOpp = Directions.iOpposite(iDir); ++ ++ node.neighbors[iDir] = neighbor; ++ neighbor.neighbors[iOpp] = node; ++ } ++ } ++ ++ return neighbor; ++ } ++ ++ private Node removeNode(BlockPos pos) { ++ return nodes.remove(pos.asLong()); ++ } ++ ++ private Node revalidateNode(Node node) { ++ node.invalid = false; ++ ++ if (node.isWire()) { ++ WireNode wire = node.asWire(); ++ ++ wire.prepared = false; ++ wire.inNetwork = false; ++ } else { ++ BlockPos pos = node.pos; ++ BlockState state = level.getBlockState(pos); ++ ++ node.update(pos, state, false); ++ } ++ ++ return node; ++ } ++ ++ /** ++ * Check the BlockState that occupies the given position. If it is a wire, then ++ * create a new WireNode. Otherwise, grab the next Node from the cache and ++ * update it. ++ */ ++ private Node getNextNode(BlockPos pos) { ++ BlockState state = level.getBlockState(pos); ++ ++ if (state.is(Blocks.REDSTONE_WIRE)) { ++ return new WireNode(level, pos, state); ++ } ++ ++ return getNextNode().update(pos, state, true); ++ } ++ ++ /** ++ * Grab the first unused Node from the cache. If all of the cache is already in ++ * use, increase it in size first. ++ */ ++ private Node getNextNode() { ++ if (nodeCount == nodeCache.length) { ++ increaseNodeCache(); ++ } ++ ++ return nodeCache[nodeCount++]; ++ } ++ ++ private void increaseNodeCache() { ++ Node[] oldCache = nodeCache; ++ nodeCache = new Node[oldCache.length << 1]; ++ ++ for (int index = 0; index < oldCache.length; index++) { ++ nodeCache[index] = oldCache[index]; ++ } ++ ++ fillNodeCache(oldCache.length, nodeCache.length); ++ } ++ ++ private void fillNodeCache(int start, int end) { ++ for (int index = start; index < end; index++) { ++ nodeCache[index] = new Node(level); ++ } ++ } ++ ++ /** ++ * This method should be called whenever a wire receives a block update. ++ */ ++ public void onWireUpdated(BlockPos pos) { ++ invalidateNodes(); ++ findRoots(pos, true); ++ tryUpdatePower(); ++ } ++ ++ /** ++ * This method should be called whenever a wire is placed. ++ */ ++ public void onWireAdded(BlockPos pos) { ++ Node node = getOrAddNode(pos); ++ ++ if (!node.isWire()) { ++ return; // we should never get here ++ } ++ ++ WireNode wire = node.asWire(); ++ wire.added = true; ++ ++ invalidateNodes(); ++ findRoots(pos, false); ++ tryUpdatePower(); ++ } ++ ++ /** ++ * This method should be called whenever a wire is removed. ++ */ ++ public void onWireRemoved(BlockPos pos, BlockState state) { ++ Node node = removeNode(pos); ++ WireNode wire; ++ ++ if (node == null || !node.isWire()) { ++ wire = new WireNode(level, pos, state); ++ } else { ++ wire = node.asWire(); ++ } ++ ++ wire.invalid = true; ++ wire.removed = true; ++ ++ // If these fields are set to 'true', the removal of this wire was part of ++ // already ongoing power changes, so we can exit early here. ++ if (updatingPower && wire.shouldBreak) { ++ return; ++ } ++ ++ invalidateNodes(); ++ tryAddRoot(wire); ++ tryUpdatePower(); ++ } ++ ++ /** ++ * The nodes map is a snapshot of the state of the world. It becomes invalid ++ * when power changes are carried out, since the block and shape updates can ++ * lead to block changes. If these block changes cause the network to be updated ++ * again every node must be invalidated, and revalidated before it is used ++ * again. This ensures the power calculations of the network are accurate. ++ */ ++ private void invalidateNodes() { ++ if (updatingPower && !nodes.isEmpty()) { ++ Iterator> it = Long2ObjectMaps.fastIterator(nodes); ++ ++ while (it.hasNext()) { ++ Entry entry = it.next(); ++ Node node = entry.getValue(); ++ ++ node.invalid = true; ++ } ++ } ++ } ++ ++ /** ++ * Look for wires at and around the given position that are in an invalid state ++ * and require power changes. These wires are called 'roots' because it is only ++ * when these wires change power level that neighboring wires must adjust as ++ * well. ++ * ++ *

++ * While it is strictly only necessary to check the wire at the given position, ++ * if that wire is part of a network, it is beneficial to check its surroundings ++ * for other wires that require power changes. This is because a network can ++ * receive power at multiple points. Consider the following setup: ++ * ++ *

++ * (top-down view, W = wire, L = lever, _ = air/other) ++ *
{@code _ _ W _ _ } ++ *
{@code _ W W W _ } ++ *
{@code W W L W W } ++ *
{@code _ W W W _ } ++ *
{@code _ _ W _ _ } ++ * ++ *

++ * The lever powers four wires in the network at once. If this is identified ++ * correctly, the entire network can (un)power at once. While it is not ++ * practical to cover every possible situation where a network is (un)powered ++ * from multiple points at once, checking for common cases like the one ++ * described above is relatively straight-forward. ++ * ++ *

++ * While these extra checks can provide significant performance gains in some ++ * cases, in the majority of cases they will have little to no effect, but do ++ * require extra code modifications to all redstone power emitters. Removing ++ * these optimizations would limit code modifications to the RedStoneWireBlock ++ * and ServerLevel classes while leaving the performance mostly intact. ++ */ ++ private void findRoots(BlockPos pos, boolean checkNeighbors) { ++ Node node = getOrAddNode(pos); ++ ++ if (!node.isWire()) { ++ return; // we should never get here ++ } ++ ++ WireNode wire = node.asWire(); ++ tryAddRoot(wire); ++ ++ // If the wire at the given position is not in an invalid state or is not ++ // part of a larger network, we can exit early. ++ if (!checkNeighbors || !wire.inNetwork || wire.connections.total == 0) { ++ return; ++ } ++ ++ for (int iDir : DEFAULT_FULL_UPDATE_ORDER) { ++ Node neighbor = getNeighbor(wire, iDir); ++ ++ if (neighbor.isConductor()) { ++ // Redstone components can power multiple wires through solid ++ // blocks. ++ findSignalSourcesAround(neighbor, Directions.iOpposite(iDir)); ++ } else if (neighbor.state.isSignalSourceTo(level, neighbor.pos, Directions.ALL[iDir])) { ++ // Redstone components can also power multiple wires directly. ++ findRootsAroundSignalSource(neighbor, Directions.iOpposite(iDir)); ++ } ++ } ++ } ++ ++ /** ++ * Find signal sources around the given node that can provide direct signals ++ * to that node, and then search for wires that require power changes around ++ * those signal sources. ++ */ ++ private void findSignalSourcesAround(Node node, int except) { ++ for (int iDir : Directions.I_EXCEPT[except]) { ++ Node neighbor = getNeighbor(node, iDir); ++ ++ if (neighbor.state.isDirectSignalSourceTo(level, neighbor.pos, Directions.ALL[iDir])) { ++ findRootsAroundSignalSource(neighbor, iDir); ++ } ++ } ++ } ++ ++ /** ++ * Find wires around the given signal source that require power changes. ++ */ ++ private void findRootsAroundSignalSource(Node node, int except) { ++ for (int iDir : Directions.I_EXCEPT[except]) { ++ // Directions are backwards for redstone related methods, so we must ++ // check for power emitted in the opposite direction that we are ++ // interested in. ++ int iOpp = Directions.iOpposite(iDir); ++ Direction opp = Directions.ALL[iOpp]; ++ ++ boolean signal = node.state.isSignalSourceTo(level, node.pos, opp); ++ boolean directSignal = node.state.isDirectSignalSourceTo(level, node.pos, opp); ++ ++ // If the signal source does not emit any power in this direction, ++ // move on to the next direction. ++ if (!signal && !directSignal) { ++ continue; ++ } ++ ++ Node neighbor = getNeighbor(node, iDir); ++ ++ if (signal && neighbor.isWire()) { ++ tryAddRoot(neighbor.asWire()); ++ } else if (directSignal && neighbor.isConductor()) { ++ findRootsAround(neighbor, iOpp); ++ } ++ } ++ } ++ ++ /** ++ * Look for wires around the given node that require power changes. ++ */ ++ private void findRootsAround(Node node, int except) { ++ for (int iDir : Directions.I_EXCEPT[except]) { ++ Node neighbor = getNeighbor(node, iDir); ++ ++ if (neighbor.isWire()) { ++ tryAddRoot(neighbor.asWire()); ++ } ++ } ++ } ++ ++ /** ++ * Check if the given wire is in an illegal state and needs power changes. ++ */ ++ private void tryAddRoot(WireNode wire) { ++ // Each potential root needs to be checked only once. ++ if (wire.prepared) { ++ return; ++ } ++ ++ prepare(wire); ++ findPower(wire, false); ++ ++ if (needsPowerChange(wire)) { ++ addRoot(wire); ++ } ++ } ++ ++ /** ++ * Add the given wire to the network as a root. ++ */ ++ private void addRoot(WireNode wire) { ++ network.add(wire); ++ rootCount++; ++ ++ wire.inNetwork = true; ++ ++ if (wire.connections.iFlowDir >= 0) { ++ wire.iFlowDir = wire.connections.iFlowDir; ++ } ++ } ++ ++ /** ++ * Before a wire can be added to the network, it must be properly prepared. ++ * This method ++ *
++ * - checks if this wire should break. Rather than break the wire right away, ++ * its effects are integrated into the power calculations. ++ *
++ * - determines the 'external power' this wire receives (power from non-wire ++ * components). ++ *
++ * - finds connections this wire has to neighboring wires. ++ */ ++ private void prepare(WireNode wire) { ++ // Each wire only needs to be prepared once. ++ if (wire.prepared) { ++ return; ++ } ++ ++ wire.prepared = true; ++ wire.inNetwork = false; ++ ++ if (!wire.removed && !wire.shouldBreak && !wire.state.canSurvive(level, wire.pos)) { ++ wire.shouldBreak = true; ++ } ++ ++ wire.virtualPower = wire.externalPower = getInitialPower(wire); ++ wire.connections.set(this::getNeighbor); ++ } ++ ++ private int getInitialPower(WireNode wire) { ++ return (wire.removed || wire.shouldBreak) ? Redstone.SIGNAL_MIN : getExternalPower(wire); ++ } ++ ++ private int getExternalPower(WireNode wire) { ++ int power = Redstone.SIGNAL_MIN; ++ ++ for (int iDir = 0; iDir < Directions.ALL.length; iDir++) { ++ Node neighbor = getNeighbor(wire, iDir); ++ ++ // Power from wires is handled separately. ++ if (neighbor.isWire()) { ++ continue; ++ } ++ ++ // Since 1.16 there is a block that is both a conductor and a signal ++ // source: the target block! ++ if (neighbor.isConductor()) { ++ power = Math.max(power, getDirectSignalTo(wire, neighbor, Directions.iOpposite(iDir))); ++ } ++ if (neighbor.isSignalSource()) { ++ power = Math.max(power, neighbor.state.getSignal(level, neighbor.pos, Directions.ALL[iDir])); ++ } ++ ++ if (power >= Redstone.SIGNAL_MAX) { ++ return Redstone.SIGNAL_MAX; ++ } ++ } ++ ++ return power; ++ } ++ ++ /** ++ * Determine the direct signal the given wire receives from neighboring blocks ++ * through the given conductor node. ++ */ ++ private int getDirectSignalTo(WireNode wire, Node node, int except) { ++ int power = Redstone.SIGNAL_MIN; ++ ++ for (int iDir : Directions.I_EXCEPT[except]) { ++ Node neighbor = getNeighbor(node, iDir); ++ ++ if (neighbor.isSignalSource()) { ++ power = Math.max(power, neighbor.state.getDirectSignal(level, neighbor.pos, Directions.ALL[iDir])); ++ ++ if (power >= Redstone.SIGNAL_MAX) { ++ return Redstone.SIGNAL_MAX; ++ } ++ } ++ } ++ ++ return power; ++ } ++ ++ /** ++ * Determine the power level the given wire receives from the blocks around it. ++ * Power from non-wire components has already been determined, so only power ++ * received from other wires needs to be checked. There are a few exceptions: ++ *
++ * - If the wire is removed or going to break, its power level should always be ++ * the minimum value. This is because it (effectively) no longer exists, so ++ * cannot provide any power to neighboring wires. ++ *
++ * - Power received from neighboring wires will never exceed {@code maxPower - 1}, ++ * so if the external power is already larger than or equal to that, there is no ++ * need to check for power from neighboring wires. ++ */ ++ private void findPower(WireNode wire, boolean ignoreNetwork) { ++ if (wire.removed || wire.shouldBreak || wire.externalPower >= (Redstone.SIGNAL_MAX - 1)) { ++ return; ++ } ++ ++ // The virtual power is reset to the external power, so the flow information ++ // must be reset as well. ++ wire.virtualPower = wire.externalPower; ++ wire.flowIn = 0; ++ ++ findWirePower(wire, ignoreNetwork); ++ } ++ ++ /** ++ * Determine the power level the given wire receives from connected wires. ++ */ ++ private void findWirePower(WireNode wire, boolean ignoreNetwork) { ++ wire.connections.forEach(connection -> { ++ if (!connection.accept) { ++ return; ++ } ++ ++ WireNode neighbor = connection.wire; ++ ++ if (!ignoreNetwork || !neighbor.inNetwork) { ++ int power = Math.max(Redstone.SIGNAL_MIN, neighbor.virtualPower - 1); ++ int iOpp = Directions.iOpposite(connection.iDir); ++ ++ wire.offerPower(power, iOpp); ++ } ++ }); ++ } ++ ++ private boolean needsPowerChange(WireNode wire) { ++ return wire.removed || wire.shouldBreak || wire.virtualPower != wire.currentPower; ++ } ++ ++ private void tryUpdatePower() { ++ if (rootCount > 0) { ++ updatePower(); ++ } ++ if (!updatingPower) { ++ nodes.clear(); ++ nodeCount = 0; ++ } ++ } ++ ++ /** ++ * Propagate power changes through the network and notify neighboring blocks of ++ * these changes. ++ * ++ *

++ * Power changes are done in the following 3 steps. ++ * ++ *

++ * 1. Build up the network ++ *
++ * Collect all the wires around the roots that need to change their power ++ * levels. ++ * ++ *

++ * 2. Find powered wires ++ *
++ * Find those wires in the network that receive power from outside the network. ++ * This can come in 2 forms: ++ *
++ * - Power from non-wire components (repeaters, torches, etc.). ++ *
++ * - Power from wires that are not in the network. ++ *
++ * These powered wires will then queue their power changes. ++ * ++ *

++ * 3. Let power flow ++ *
++ * Work through the queue of power changes. After each wire's power change, emit ++ * shape and block updates to neighboring blocks, then queue power changes for ++ * connected wires. ++ */ ++ private void updatePower() { ++ // Build a network of wires that need power changes. This includes the roots ++ // as well as any wires that will be affected by power changes to those roots. ++ buildNetwork(); ++ ++ // Find those wires in the network that receive power from outside it. ++ // Remember that the power changes for those wires are already queued here! ++ findPoweredWires(); ++ ++ // Once the powered wires have been found, the network is no longer needed. In ++ // fact, it should be cleared before block and shape updates are emitted, in ++ // case a different network is updated that needs power changes. ++ network.clear(); ++ rootCount = 0; ++ ++ // Carry out the power changes and emit shape and block updates. ++ try { ++ letPowerFlow(); ++ } catch (Throwable t) { ++ // If anything goes wrong while carrying out power changes, this field must ++ // be reset to 'false', or the wire handler will be locked out of carrying ++ // out power changes until the world is reloaded. ++ updatingPower = false; ++ ++ throw t; ++ } ++ } ++ ++ /** ++ * Build up a network of wires that need power changes. This includes the roots ++ * that were already added and any wires powered by those roots that will need ++ * power changes as a result of power changes to the roots. ++ */ ++ private void buildNetwork() { ++ for (int index = 0; index < network.size(); index++) { ++ WireNode wire = network.get(index); ++ ++ // The order in which wires are added to the network can influence the ++ // order in which they update their power levels. ++ wire.connections.forEach(connection -> { ++ if (!connection.offer) { ++ return; ++ } ++ ++ WireNode neighbor = connection.wire; ++ ++ if (neighbor.inNetwork) { ++ return; ++ } ++ ++ prepare(neighbor); ++ findPower(neighbor, false); ++ ++ if (needsPowerChange(neighbor)) { ++ addToNetwork(neighbor, connection.iDir); ++ } ++ }, wire.iFlowDir); ++ } ++ } ++ ++ /** ++ * Add the given wire to the network and set its outgoing flow to some backup ++ * value. This avoids directionality in redstone grids. ++ */ ++ private void addToNetwork(WireNode wire, int iBackupFlowDir) { ++ network.add(wire); ++ ++ wire.inNetwork = true; ++ // Normally the flow is not set until the power level is updated. However, ++ // in networks with multiple power sources the update order between them ++ // depends on which was discovered first. To make this less prone to ++ // directionality, each wire node is given a 'backup' flow. For roots, this ++ // is the determined flow of their connections. For non-roots this is the ++ // direction from which they were discovered. ++ wire.iFlowDir = iBackupFlowDir; ++ } ++ ++ /** ++ * Find those wires in the network that receive power from outside it, either ++ * from non-wire components or from wires that are not in the network, and queue ++ * the power changes for those wires. ++ */ ++ private void findPoweredWires() { ++ for (int index = 0; index < network.size(); index++) { ++ WireNode wire = network.get(index); ++ findPower(wire, true); ++ ++ if (index < rootCount || wire.removed || wire.shouldBreak || wire.virtualPower > Redstone.SIGNAL_MIN) { ++ queuePowerChange(wire); ++ } else { ++ // Wires that do not receive any power do not queue power changes ++ // until they are offered power from a neighboring wire. To ensure ++ // that they accept any power from neighboring wires and thus queue ++ // their power changes, their virtual power is set to below the ++ // minimum. ++ wire.virtualPower--; ++ } ++ } ++ } ++ ++ /** ++ * Queue the power change for the given wire. If the wire does not need a power ++ * change (perhaps because its power has already changed), transmit power to ++ * neighboring wires. ++ */ ++ private void queuePowerChange(WireNode wire) { ++ if (needsPowerChange(wire)) { ++ powerChanges.offer(wire); ++ } else { ++ findPowerFlow(wire); ++ transmitPower(wire); ++ } ++ } ++ ++ /** ++ * Use the information of incoming power flow to determine the direction of ++ * power flow through this wire. If that flow is ambiguous, try to use a flow ++ * direction based on connections to neighboring wires. If that is also ++ * ambiguous, use the backup value that was set when the wire was first added ++ * to the network. ++ */ ++ private void findPowerFlow(WireNode wire) { ++ int flow = FLOW_IN_TO_FLOW_OUT[wire.flowIn]; ++ ++ if (flow >= 0) { ++ wire.iFlowDir = flow; ++ } else if (wire.connections.iFlowDir >= 0) { ++ wire.iFlowDir = wire.connections.iFlowDir; ++ } ++ } ++ ++ /** ++ * Transmit power from the given wire to neighboring wires. ++ */ ++ private void transmitPower(WireNode wire) { ++ int nextPower = Math.max(Redstone.SIGNAL_MIN, wire.virtualPower - 1); ++ ++ wire.connections.forEach(connection -> { ++ if (!connection.offer) { ++ return; ++ } ++ ++ WireNode neighbor = connection.wire; ++ int iDir = connection.iDir; ++ ++ if (neighbor.offerPower(nextPower, iDir)) { ++ queuePowerChange(neighbor); ++ } ++ }, wire.iFlowDir); ++ } ++ ++ /** ++ * Carry out power changes, setting the new power of each wire in the world, ++ * notifying neighbors of the power change, then queueing power changes of ++ * connected wires. ++ */ ++ private void letPowerFlow() { ++ // If an instantaneous update chain causes updates to another network ++ // (or the same network in another place), new power changes will be ++ // integrated into the already ongoing power queue, so we can exit early ++ // here. ++ if (updatingPower) { ++ return; ++ } ++ ++ updatingPower = true; ++ ++ while (!powerChanges.isEmpty()) { ++ WireNode wire = powerChanges.poll(); ++ ++ if (!needsPowerChange(wire)) { ++ continue; ++ } ++ ++ findPowerFlow(wire); ++ ++ if (wire.setPower()) { ++ // If the wire was newly placed or removed, shape updates have ++ // already been emitted. ++ if (!wire.added && !wire.shouldBreak) { ++ updateNeighborShapes(wire); ++ } ++ ++ updateNeighborBlocks(wire); ++ } ++ ++ transmitPower(wire); ++ } ++ ++ updatingPower = false; ++ } ++ ++ /** ++ * Emit shape updates around the given wire. ++ */ ++ private void updateNeighborShapes(WireNode wire) { ++ BlockPos wirePos = wire.pos; ++ BlockState wireState = wire.state; ++ ++ for (Direction dir : Block.UPDATE_SHAPE_ORDER) { ++ updateNeighborShape(wirePos.relative(dir), dir.getOpposite(), wirePos, wireState); ++ } ++ } ++ ++ private void updateNeighborShape(BlockPos pos, Direction fromDir, BlockPos fromPos, BlockState fromState) { ++ BlockState state = level.getBlockState(pos); ++ ++ // Shape updates to redstone wire are very expensive, and should never happen ++ // as a result of power changes anyway. ++ if (!state.isAir() && !state.is(Blocks.REDSTONE_WIRE)) { ++ BlockState newState = state.updateShape(fromDir, fromState, level, pos, fromPos); ++ Block.updateOrDestroy(state, newState, level, pos, Block.UPDATE_CLIENTS); ++ } ++ } ++ ++ /** ++ * Emit block updates around the given wire. The order in which neighbors are ++ * updated is determined as follows: ++ *
++ * 1. The direction of power flow through the wire is to be considered 'forward'. ++ * The order in which neighbors are updated depends on their relative positions ++ * to the wire. ++ *
++ * 2. Each neighbor is identified by the step(s) you must take, starting at the ++ * wire, to reach it. Each step is 1 block, thus the position of a neighbor is ++ * encoded by the direction(s) of the step(s), e.g. (right), (down), (up, left), ++ * etc. ++ *
++ * 3. Neighbors are updated in pairs that lie on opposite sides of the wire. ++ *
++ * 4. Neighbors are updated in order of their distance from the wire. This means ++ * they are updated in 3 groups: direct neighbors are updated first, then ++ * diagonal neighbors, and last are the far neighbors that are 2 blocks directly ++ * out. ++ *
++ * 5. The order within each group is determined using the following basic order: ++ * { front, back, right, left, down, up }. This order was chosen because it ++ * converts to the following order of absolute directions when west is said to ++ * be 'forward': { west, east, north, south, down, up } - this is the order of ++ * shape updates. ++ */ ++ private void updateNeighborBlocks(WireNode wire) { ++ int iDir = wire.iFlowDir; ++ ++ Direction forward = Directions.HORIZONTAL[ iDir ]; ++ Direction rightward = Directions.HORIZONTAL[(iDir + 1) & 0b11]; ++ Direction backward = Directions.HORIZONTAL[(iDir + 2) & 0b11]; ++ Direction leftward = Directions.HORIZONTAL[(iDir + 3) & 0b11]; ++ Direction downward = Direction.DOWN; ++ Direction upward = Direction.UP; ++ ++ BlockPos self = wire.pos; ++ BlockPos front = self.relative(forward); ++ BlockPos right = self.relative(rightward); ++ BlockPos back = self.relative(backward); ++ BlockPos left = self.relative(leftward); ++ BlockPos below = self.relative(downward); ++ BlockPos above = self.relative(upward); ++ ++ // direct neighbors (6) ++ updateNeighbor(front, self); ++ updateNeighbor(back, self); ++ updateNeighbor(right, self); ++ updateNeighbor(left, self); ++ updateNeighbor(below, self); ++ updateNeighbor(above, self); ++ ++ // diagonal neighbors (12) ++ updateNeighbor(front.relative(rightward), self); ++ updateNeighbor(back.relative(leftward), self); ++ updateNeighbor(front.relative(leftward), self); ++ updateNeighbor(back.relative(rightward), self); ++ updateNeighbor(front.relative(downward), self); ++ updateNeighbor(back.relative(upward), self); ++ updateNeighbor(front.relative(upward), self); ++ updateNeighbor(back.relative(downward), self); ++ updateNeighbor(right.relative(downward), self); ++ updateNeighbor(left.relative(upward), self); ++ updateNeighbor(right.relative(upward), self); ++ updateNeighbor(left.relative(downward), self); ++ ++ // far neighbors (6) ++ updateNeighbor(front.relative(forward), self); ++ updateNeighbor(back.relative(backward), self); ++ updateNeighbor(right.relative(rightward), self); ++ updateNeighbor(left.relative(leftward), self); ++ updateNeighbor(below.relative(downward), self); ++ updateNeighbor(above.relative(upward), self); ++ } ++ ++ private void updateNeighbor(BlockPos pos, BlockPos fromPos) { ++ BlockState state = level.getBlockState(pos); ++ ++ // While this check makes sure wires in the network are not given block ++ // updates, it also prevents block updates to wires in neighboring networks. ++ // While this should not make a difference in theory, in practice, it is ++ // possible to force a network into an invalid state without updating it, even ++ // if it is relatively obscure. ++ // While I was willing to make this compromise in return for some significant ++ // performance gains in certain setups, if you are not, you can add all the ++ // positions of the network to a set and filter out block updates to wires in ++ // the network that way. ++ if (!state.isAir() && !state.is(Blocks.REDSTONE_WIRE)) { ++ state.neighborChanged(level, pos, Blocks.REDSTONE_WIRE, fromPos, false); ++ } ++ } ++ ++ @FunctionalInterface ++ public interface NodeProvider { ++ ++ public Node getNeighbor(Node node, int iDir); ++ ++ } ++} +diff --git a/src/main/java/alternate/current/wire/WireNode.java b/src/main/java/alternate/current/wire/WireNode.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6b5bffd288e2f815d8c3788e73530e69d549e25e +--- /dev/null ++++ b/src/main/java/alternate/current/wire/WireNode.java +@@ -0,0 +1,117 @@ ++package alternate.current.wire; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.util.Mth; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.world.level.block.Block; ++import net.minecraft.world.level.block.Blocks; ++import net.minecraft.world.level.block.RedStoneWireBlock; ++import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.redstone.Redstone; ++ ++/** ++ * A WireNode is a Node that represents a wire in the world. It stores ++ * all the information about the wire that the WireHandler needs to ++ * calculate power changes. ++ * ++ * @author Space Walker ++ */ ++public class WireNode extends Node { ++ ++ final WireConnectionManager connections; ++ ++ /** The power level this wire currently holds in the world. */ ++ int currentPower; ++ /** ++ * While calculating power changes for a network, this field is used to keep ++ * track of the power level this wire should have. ++ */ ++ int virtualPower; ++ /** The power level received from non-wire components. */ ++ int externalPower; ++ /** ++ * A 4-bit number that keeps track of the power flow of the wires that give this ++ * wire its power level. ++ */ ++ int flowIn; ++ /** The direction of power flow, based on the incoming flow. */ ++ int iFlowDir; ++ boolean added; ++ boolean removed; ++ boolean shouldBreak; ++ boolean prepared; ++ boolean inNetwork; ++ ++ /** The power for which this wire was queued. */ ++ int power; ++ /** The previous wire in the power queue. */ ++ WireNode prev; ++ /** The next wire in the power queue. */ ++ WireNode next; ++ ++ WireNode(ServerLevel level, BlockPos pos, BlockState state) { ++ super(level); ++ ++ this.pos = pos.immutable(); ++ this.state = state; ++ ++ this.connections = new WireConnectionManager(this); ++ ++ this.virtualPower = this.currentPower = this.state.getValue(RedStoneWireBlock.POWER); ++ } ++ ++ @Override ++ public Node update(BlockPos pos, BlockState state, boolean clearNeighbors) { ++ throw new UnsupportedOperationException("Cannot update a WireNode!"); ++ } ++ ++ @Override ++ public boolean isWire() { ++ return true; ++ } ++ ++ @Override ++ public WireNode asWire() { ++ return this; ++ } ++ ++ int nextPower() { ++ return Mth.clamp(virtualPower, Redstone.SIGNAL_MIN, Redstone.SIGNAL_MAX); ++ } ++ ++ boolean offerPower(int power, int iDir) { ++ if (removed || shouldBreak) { ++ return false; ++ } ++ if (power == virtualPower) { ++ flowIn |= (1 << iDir); ++ return false; ++ } ++ if (power > virtualPower) { ++ virtualPower = power; ++ flowIn = (1 << iDir); ++ ++ return true; ++ } ++ ++ return false; ++ } ++ ++ boolean setPower() { ++ if (removed) { ++ return true; ++ } ++ ++ state = level.getBlockState(pos); ++ ++ if (shouldBreak) { ++ Block.dropResources(state, level, pos); ++ return level.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS); ++ } ++ ++ currentPower = LevelHelper.doRedstoneEvent(level, pos, currentPower, power); ++ state = state.setValue(RedStoneWireBlock.POWER, currentPower); ++ ++ return LevelHelper.setWireState(level, pos, state, added); ++ } ++} +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 2d87ebd657db2977b95c2f5707a36a313444b6e4..246cfce07c74f42f8c1efb2b4e2b8ec086d5e58f 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -82,13 +82,41 @@ public class PaperWorldConfig { + piglinsGuardChests = getBoolean("piglins-guard-chests", piglinsGuardChests); + } + +- public boolean useEigencraftRedstone = false; +- private void useEigencraftRedstone() { +- useEigencraftRedstone = this.getBoolean("use-faster-eigencraft-redstone", false); +- if (useEigencraftRedstone) { +- log("Using Eigencraft redstone algorithm by theosib."); ++ public enum RedstoneImplementation { ++ VANILLA, EIGENCRAFT, ALTERNATE_CURRENT ++ } ++ public RedstoneImplementation redstoneImplementation = RedstoneImplementation.VANILLA; ++ private void redstoneImplementation() { ++ String implementation; ++ if (PaperConfig.version < 27) { ++ implementation = "vanilla"; ++ if (config.contains("world-settings.default.use-faster-eigencraft-redstone")) { ++ implementation = config.getBoolean("world-settings.default.use-faster-eigencraft-redstone") ? "eigencraft" : "vanilla"; ++ config.set("world-settings.default.redstone-implementation", implementation); ++ } ++ if (config.contains("world-settings." + worldName + ".use-faster-eigencraft-redstone")) { ++ implementation = config.getBoolean("world-settings." + worldName + ".use-faster-eigencraft-redstone") ? "eigencraft" : "vanilla"; ++ config.set("world-settings." + worldName + ".redstone-implementation", implementation); ++ } ++ remove("use-faster-eigencraft-redstone"); + } else { +- log("Using vanilla redstone algorithm."); ++ implementation = this.getString("redstone-implementation", "vanilla").toLowerCase().trim(); ++ } ++ switch (implementation) { ++ default: ++ logError("Invalid redstone-implementation config " + implementation + " - must be one of: vanilla, eigencraft, alternate-current"); ++ case "vanilla": ++ redstoneImplementation = RedstoneImplementation.VANILLA; ++ log("Using the Vanilla redstone implementation."); ++ break; ++ case "eigencraft": ++ redstoneImplementation = RedstoneImplementation.EIGENCRAFT; ++ log("Using Eigencraft's redstone implementation by theosib."); ++ break; ++ case "alternate-current": ++ redstoneImplementation = RedstoneImplementation.ALTERNATE_CURRENT; ++ log("Using Alternate Current's redstone implementation by Space Walker."); ++ break; + } + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 62ec40de8ed8acb293ef21c8d2c624060d51cfe8..98209532ad3e692d7e459640123f78bbd9a65889 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -212,6 +212,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + public final UUID uuid; + public boolean hasPhysicsEvent = true; // Paper + public boolean hasEntityMoveEvent = false; // Paper ++ private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) + public static Throwable getAddToWorldStackTrace(Entity entity) { + return new Throwable(entity + " Added to world at " + new java.util.Date()); + } +@@ -2407,6 +2408,13 @@ public class ServerLevel extends Level implements WorldGenLevel { + return this.entityManager.canPositionTick(pos.toLong()); // Paper + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public alternate.current.wire.WireHandler getWireHandler() { ++ return wireHandler; ++ } ++ // Paper end ++ + private final class EntityCallbacks implements LevelCallback { + + EntityCallbacks() {} +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 160c0f37aa3aaf7598f852acf9bd444f79444c97..aece6a47d978e9d3579334bbedadfeb9f4770894 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -1499,4 +1499,15 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return ret; + } + // Paper end ++ ++ // Paper start - optimize redstone (Alternate Current) ++ public alternate.current.wire.WireHandler getWireHandler() { ++ // This method is overridden in ServerLevel. ++ // Since Paper is a server platform there is no risk ++ // of this implementation being called. It is here ++ // only so this method can be called without casting ++ // an instance of Level to ServerLevel. ++ return null; ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +index 2036006b934ba1f27da606320b4c456af019a361..9d1d59fe26eff0640906037aba93e73dda433d0d 100644 +--- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +@@ -153,6 +153,18 @@ public abstract class BasePressurePlateBlock extends Block { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return dir == Direction.UP; ++ } ++ // Paper end ++ + @Override + public PushReaction getPistonPushReaction(BlockState state) { + return PushReaction.DESTROY; +diff --git a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +index b7f37475192bf79252482314080c9ba08e9aefdb..8b6eeb1ccad3a2e3858b70e59819c79485a2e538 100644 +--- a/src/main/java/net/minecraft/world/level/block/ButtonBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ButtonBlock.java +@@ -159,6 +159,18 @@ public abstract class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return getConnectedDirection(state) == dir; ++ } ++ // Paper end ++ + @Override + public void tick(BlockState state, ServerLevel world, BlockPos pos, Random random) { + if ((Boolean) state.getValue(ButtonBlock.POWERED)) { +diff --git a/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java b/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java +index 40b0380aa6fd052bf6376a15939c08e603f2f60c..e57c5242866165e589277bd0184098c7806538ba 100644 +--- a/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java +@@ -99,6 +99,13 @@ public class DaylightDetectorBlock extends BaseEntityBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ // Paper end ++ + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new DaylightDetectorBlockEntity(pos, state); +diff --git a/src/main/java/net/minecraft/world/level/block/DiodeBlock.java b/src/main/java/net/minecraft/world/level/block/DiodeBlock.java +index 9c764d2273d70b8dffcaa7f324544cb48f12acc3..7f0aa1e8b53a749459fb8cb99c73c6c2c60ea4e9 100644 +--- a/src/main/java/net/minecraft/world/level/block/DiodeBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/DiodeBlock.java +@@ -159,6 +159,18 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) == dir; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) == dir; ++ } ++ // Paper end ++ + @Override + public BlockState getStateForPlacement(BlockPlaceContext ctx) { + return (BlockState) this.defaultBlockState().setValue(DiodeBlock.FACING, ctx.getHorizontalDirection().getOpposite()); +diff --git a/src/main/java/net/minecraft/world/level/block/LecternBlock.java b/src/main/java/net/minecraft/world/level/block/LecternBlock.java +index 25ed6dfef2887612a02fcf8884dc8dac4fbd64ff..7f6f14e7858c2577e44ace8370621114dce29ea8 100644 +--- a/src/main/java/net/minecraft/world/level/block/LecternBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LecternBlock.java +@@ -220,6 +220,18 @@ public class LecternBlock extends BaseEntityBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return dir == Direction.UP; ++ } ++ // Paper end; ++ + @Override + public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { + return (Boolean) state.getValue(LecternBlock.POWERED) ? 15 : 0; +diff --git a/src/main/java/net/minecraft/world/level/block/LeverBlock.java b/src/main/java/net/minecraft/world/level/block/LeverBlock.java +index 1093dc8595e42a90e74e19f74965f5be07a1d6cf..6e7320f5b8e2cf030b96f2ab80c8fb885b0fe1e3 100644 +--- a/src/main/java/net/minecraft/world/level/block/LeverBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LeverBlock.java +@@ -165,6 +165,18 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return getConnectedDirection(state) == dir; ++ } ++ // Paper end ++ + private void updateNeighbours(BlockState state, Level world, BlockPos pos) { + world.updateNeighborsAt(pos, this); + world.updateNeighborsAt(pos.relative(getConnectedDirection(state).getOpposite()), this); +diff --git a/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java b/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java +index b7605dda79c4d907f5822a0ded694b080e08dae5..ff24cbf03e937572a0c21fe298557d4eab8760b9 100644 +--- a/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java +@@ -166,4 +166,16 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc + public boolean isSignalSource(BlockState state) { + return true; + } ++ ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) == dir; ++ } ++ // Paper end + } +diff --git a/src/main/java/net/minecraft/world/level/block/ObserverBlock.java b/src/main/java/net/minecraft/world/level/block/ObserverBlock.java +index 4a34a08a1d46e4d3020644a51d9e30a36a18791a..358a40eb9b4be4d2b5446270f90b51138a19b051 100644 +--- a/src/main/java/net/minecraft/world/level/block/ObserverBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/ObserverBlock.java +@@ -90,6 +90,18 @@ public class ObserverBlock extends DirectionalBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) == dir; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) == dir; ++ } ++ // Paper end ++ + @Override + public int getDirectSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { + return state.getSignal(world, pos, direction); +diff --git a/src/main/java/net/minecraft/world/level/block/PoweredBlock.java b/src/main/java/net/minecraft/world/level/block/PoweredBlock.java +index 0afffc33f3be221a28c62115f493808aeffb1bd8..def39cd02da68b9be1ecfa5ae70119ef862cd079 100644 +--- a/src/main/java/net/minecraft/world/level/block/PoweredBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/PoweredBlock.java +@@ -3,6 +3,7 @@ package net.minecraft.world.level.block; + import net.minecraft.core.BlockPos; + import net.minecraft.core.Direction; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.state.BlockBehaviour; + import net.minecraft.world.level.block.state.BlockState; + +@@ -16,6 +17,13 @@ public class PoweredBlock extends Block { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ // Paper end ++ + @Override + public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { + return 15; +diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +index 037330bcb10039c013b2ed5fd68dee16ede20fbe..dc545de83ef374e70712d5b20beb4b87fef1cf76 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.level.block; + + import com.destroystokyo.paper.PaperConfig; ++import com.destroystokyo.paper.PaperWorldConfig.RedstoneImplementation; + import com.destroystokyo.paper.util.RedstoneWireTurbo; + import com.google.common.collect.ImmutableMap; + import com.google.common.collect.Maps; +@@ -257,7 +258,7 @@ public class RedStoneWireBlock extends Block { + return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER); + } + +- // Paper start - Optimize redstone ++ // Paper start - Optimize redstone (Eigencraft) + // The bulk of the new functionality is found in RedstoneWireTurbo.java + RedstoneWireTurbo turbo = new RedstoneWireTurbo(this); + +@@ -267,7 +268,7 @@ public class RedStoneWireBlock extends Block { + * Note: Added 'source' argument so as to help determine direction of information flow + */ + private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, BlockPos source) { +- if (worldIn.paperConfig.useEigencraftRedstone) { ++ if (worldIn.paperConfig.redstoneImplementation == RedstoneImplementation.EIGENCRAFT) { + turbo.updateSurroundingRedstone(worldIn, pos, state, source); + return; + } +@@ -291,7 +292,7 @@ public class RedStoneWireBlock extends Block { + int k = worldIn.getBestNeighborSignal(pos1); + this.shouldSignal = true; + +- if (!worldIn.paperConfig.useEigencraftRedstone) { ++ if (worldIn.paperConfig.redstoneImplementation == RedstoneImplementation.VANILLA) { + // This code is totally redundant to if statements just below the loop. + if (k > 0 && k > j - 1) { + j = k; +@@ -305,7 +306,7 @@ public class RedStoneWireBlock extends Block { + // redstone wire will be set to 'k'. If 'k' is already 15, then nothing inside the + // following loop can affect the power level of the wire. Therefore, the loop is + // skipped if k is already 15. +- if (!worldIn.paperConfig.useEigencraftRedstone || k < 15) { ++ if (worldIn.paperConfig.redstoneImplementation == RedstoneImplementation.VANILLA || k < 15) { + for (Direction enumfacing : Direction.Plane.HORIZONTAL) { + BlockPos blockpos = pos1.relative(enumfacing); + boolean flag = blockpos.getX() != pos2.getX() || blockpos.getZ() != pos2.getZ(); +@@ -324,7 +325,7 @@ public class RedStoneWireBlock extends Block { + } + } + +- if (!worldIn.paperConfig.useEigencraftRedstone) { ++ if (worldIn.paperConfig.redstoneImplementation == RedstoneImplementation.VANILLA) { + // The old code would decrement the wire value only by 1 at a time. + if (l > j) { + j = l - 1; +@@ -464,7 +465,13 @@ public class RedStoneWireBlock extends Block { + @Override + public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) { + if (!oldState.is(state.getBlock()) && !world.isClientSide) { +- this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone ++ // Paper start - optimize redstone - replace call to updatePowerStrength ++ if (world.paperConfig.redstoneImplementation == RedstoneImplementation.ALTERNATE_CURRENT) { ++ world.getWireHandler().onWireAdded(pos); // Alternate Current ++ } else { ++ this.updateSurroundingRedstone(world, pos, state, null); // vanilla/Eigencraft ++ } ++ // Paper end + Iterator iterator = Direction.Plane.VERTICAL.iterator(); + + while (iterator.hasNext()) { +@@ -491,7 +498,13 @@ public class RedStoneWireBlock extends Block { + world.updateNeighborsAt(pos.relative(enumdirection), this); + } + +- this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone ++ // Paper start - optimize redstone - replace call to updatePowerStrength ++ if (world.paperConfig.redstoneImplementation == RedstoneImplementation.ALTERNATE_CURRENT) { ++ world.getWireHandler().onWireRemoved(pos, state); // Alternate Current ++ } else { ++ this.updateSurroundingRedstone(world, pos, state, null); // vanilla/Eigencraft ++ } ++ // Paper end + this.updateNeighborsOfNeighboringWires(world, pos); + } + } +@@ -525,8 +538,14 @@ public class RedStoneWireBlock extends Block { + @Override + public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) { + if (!world.isClientSide) { ++ // Paper start - optimize redstone (Alternate Current) ++ // Alternate Current handles breaking of redstone wires in the WireHandler. ++ if (world.paperConfig.redstoneImplementation == RedstoneImplementation.ALTERNATE_CURRENT) { ++ world.getWireHandler().onWireUpdated(pos); ++ } else ++ // Paper end + if (state.canSurvive(world, pos)) { +- this.updateSurroundingRedstone(world, pos, state, fromPos); // Paper - Optimize redstone ++ this.updateSurroundingRedstone(world, pos, state, fromPos); // Paper - optimize redstone (Eigencraft) + } else { + dropResources(state, world, pos); + world.removeBlock(pos, false); +diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +index 954b86bea345a8e0e3a8dd425f356db6f5cd496f..3731749436c86210954e4213f893a51eea06230a 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +@@ -139,6 +139,18 @@ public class RedstoneTorchBlock extends TorchBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return dir != Direction.UP; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return dir == Direction.DOWN; ++ } ++ // Paper end ++ + @Override + public void animateTick(BlockState state, Level world, BlockPos pos, Random random) { + if ((Boolean) state.getValue(RedstoneTorchBlock.LIT)) { +diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneWallTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneWallTorchBlock.java +index 5cf0ae04059533385a19f7b07909a67b57350c09..ec5c201ebac0e1b44b90319884ce968a9212f3b2 100644 +--- a/src/main/java/net/minecraft/world/level/block/RedstoneWallTorchBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/RedstoneWallTorchBlock.java +@@ -76,6 +76,13 @@ public class RedstoneWallTorchBlock extends RedstoneTorchBlock { + return state.getValue(LIT) && state.getValue(FACING) != direction ? 15 : 0; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) != dir; ++ } ++ // Paper end ++ + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + return Blocks.WALL_TORCH.rotate(state, rotation); +diff --git a/src/main/java/net/minecraft/world/level/block/SculkSensorBlock.java b/src/main/java/net/minecraft/world/level/block/SculkSensorBlock.java +index 33bca696c1ae0a63055eea5d2e05551458da50b4..4a0e4b9c49f04d63ca0b7d0a6ce71680f911ff29 100644 +--- a/src/main/java/net/minecraft/world/level/block/SculkSensorBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/SculkSensorBlock.java +@@ -206,6 +206,13 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ // Paper end ++ + @Override + public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { + return (Integer) state.getValue(SculkSensorBlock.POWER); +diff --git a/src/main/java/net/minecraft/world/level/block/TargetBlock.java b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +index d609c60c1650a5b7f860154e0a4f4c6d84fa63fc..391d64b698871aa420f736a97b7b4b28c9d11da0 100644 +--- a/src/main/java/net/minecraft/world/level/block/TargetBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TargetBlock.java +@@ -113,6 +113,13 @@ public class TargetBlock extends Block { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ // Paper end ++ + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(OUTPUT_POWER); +diff --git a/src/main/java/net/minecraft/world/level/block/TrappedChestBlock.java b/src/main/java/net/minecraft/world/level/block/TrappedChestBlock.java +index 184c70cd2954f4904518c3fee2a377d9c4e81cc3..78a3d810cbb4c0da8c59a9b225e9241945520586 100644 +--- a/src/main/java/net/minecraft/world/level/block/TrappedChestBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TrappedChestBlock.java +@@ -7,6 +7,7 @@ import net.minecraft.stats.Stat; + import net.minecraft.stats.Stats; + import net.minecraft.util.Mth; + import net.minecraft.world.level.BlockGetter; ++import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.entity.BlockEntity; + import net.minecraft.world.level.block.entity.BlockEntityType; + import net.minecraft.world.level.block.entity.ChestBlockEntity; +@@ -36,6 +37,18 @@ public class TrappedChestBlock extends ChestBlock { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return dir == Direction.UP; ++ } ++ // Paper end ++ + @Override + public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { + return Mth.clamp(ChestBlockEntity.getOpenCount(world, pos), 0, 15); +diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +index a4344bf2267112e3c1e31c07c9f6b8eae9666947..5e973eb53b240615e70b7d46ef4dc17b907ecaf9 100644 +--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +@@ -265,6 +265,18 @@ public class TripWireHookBlock extends Block { + return true; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ @Override ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return true; ++ } ++ ++ @Override ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return state.getValue(FACING) == dir; ++ } ++ // Paper end ++ + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + return (BlockState) state.setValue(TripWireHookBlock.FACING, rotation.rotate((Direction) state.getValue(TripWireHookBlock.FACING))); +diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +index 61590f2f04a797235299f1bd6b78a08f5bfe4a33..15e1d54cb53bcdf962b799d1deb2cade6491b433 100644 +--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java ++++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java +@@ -70,7 +70,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; + + public abstract class BlockBehaviour { + +- protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP}; ++ public static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP}; + protected final Material material; + public final boolean hasCollision; + protected final float explosionResistance; +@@ -187,6 +187,16 @@ public abstract class BlockBehaviour { + return false; + } + ++ // Paper start - optimize redstone (Alternate Current) ++ public boolean isSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return false; ++ } ++ ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, BlockState state, Direction dir) { ++ return false; ++ } ++ // Paper end ++ + /** @deprecated */ + @Deprecated + public PushReaction getPistonPushReaction(BlockState state) { +@@ -846,6 +856,16 @@ public abstract class BlockBehaviour { + return this.getBlock().isSignalSource(this.asState()); + } + ++ // Paper start - optimize redstone (Alternate Current) ++ public boolean isSignalSourceTo(Level level, BlockPos pos, Direction dir) { ++ return this.getBlock().isSignalSourceTo(level, pos, this.asState(), dir); ++ } ++ ++ public boolean isDirectSignalSourceTo(Level level, BlockPos pos, Direction dir) { ++ return this.getBlock().isDirectSignalSourceTo(level, pos, this.asState(), dir); ++ } ++ // Paper end ++ + public int getSignal(BlockGetter world, BlockPos pos, Direction direction) { + return this.getBlock().getSignal(this.asState(), world, pos, direction); + }