-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
66b078c
commit 710267d
Showing
2 changed files
with
261 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: violetc <[email protected]> | ||
Date: Thu, 3 Aug 2023 14:21:55 +0800 | ||
Subject: [PATCH] Force peaceful mode switch | ||
|
||
|
||
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java | ||
index 6917931966377c51db88a3364997a110dd987970..ff145aba03c3ba20cb1d905705ff350d77dbc336 100644 | ||
--- a/src/main/java/org/bukkit/World.java | ||
+++ b/src/main/java/org/bukkit/World.java | ||
@@ -4000,6 +4000,12 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient | ||
@NotNull | ||
public Set<FeatureFlag> getFeatureFlags(); | ||
|
||
+ // Leaves start - unsupported settings | ||
+ public void setPeacefulModeSwitchTick(int tick); | ||
+ | ||
+ public int getPeacefulModeSwitchTick(int tick); | ||
+ // Leaves end - unsupported settings | ||
+ | ||
/** | ||
* Represents various map environment types that a world may be | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: violetc <[email protected]> | ||
Date: Thu, 3 Aug 2023 14:21:47 +0800 | ||
Subject: [PATCH] Force peaceful mode switch | ||
|
||
|
||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java | ||
index 47787f1f86b99cfcae6e1bb3dcf7648e9f04c936..d9da306d2675201beedddd43dcef18b31a2fa0e0 100644 | ||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java | ||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java | ||
@@ -82,6 +82,12 @@ public class ServerChunkCache extends ChunkSource { | ||
public final java.util.concurrent.atomic.AtomicBoolean spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false); | ||
// Leaves end - optimize mob spawning | ||
|
||
+ // Leaves start - peaceful mode switch | ||
+ public int peacefulModeSwitchTick = -1; | ||
+ public int peacefulModeSwitchCount = -1; | ||
+ private final List<Class<? extends Entity>> peacefulModeSwitchEntityTypes = List.of(net.minecraft.world.entity.boss.wither.WitherBoss.class, net.minecraft.world.entity.monster.Shulker.class, net.minecraft.world.entity.monster.warden.Warden.class); | ||
+ // Leaves end - peaceful mode switch | ||
+ | ||
private static int getChunkCacheKey(int x, int z) { | ||
return x & 3 | ((z & 3) << 2); | ||
} | ||
@@ -563,6 +569,22 @@ public class ServerChunkCache extends ChunkSource { | ||
this.level.resetIceAndSnowTick(); | ||
} | ||
// Leaves end - reset ice & snow tick random | ||
+ | ||
+ // Leaves start - peaceful mode switch | ||
+ if (peacefulModeSwitchTick > 0) { | ||
+ if (this.level.getLevelData().getGameTime() % peacefulModeSwitchTick == 0) { | ||
+ peacefulModeSwitchCount = 0; | ||
+ this.level.getAllEntities().forEach(entity -> { | ||
+ if (peacefulModeSwitchEntityTypes.contains(entity.getClass())) { | ||
+ peacefulModeSwitchCount++; | ||
+ } | ||
+ }); | ||
+ } | ||
+ } else { | ||
+ peacefulModeSwitchCount = -1; | ||
+ } | ||
+ // Leaves end - peaceful mode switch | ||
+ | ||
int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); | ||
boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit | ||
|
||
@@ -624,6 +646,15 @@ public class ServerChunkCache extends ChunkSource { | ||
iterator1 = shuffled.iterator(); | ||
} | ||
|
||
+ // Leaves start - peaceful mode switch | ||
+ boolean peacefulModeSwitch = false; | ||
+ if (lastSpawnState != null && peacefulModeSwitchCount != -1) { | ||
+ if (peacefulModeSwitchCount >= NaturalSpawner.globalLimitForCategory(level, net.minecraft.world.entity.MobCategory.MONSTER, lastSpawnState.getSpawnableChunkCount())) { | ||
+ peacefulModeSwitch = true; | ||
+ } | ||
+ } | ||
+ // Leaves end - peaceful mode switch | ||
+ | ||
int chunksTicked = 0; // Paper | ||
try { | ||
while (iterator1.hasNext()) { | ||
@@ -638,7 +669,7 @@ public class ServerChunkCache extends ChunkSource { | ||
chunk1.incrementInhabitedTime(j); | ||
// Leaves start - optimize mob spawning | ||
if ((top.leavesmc.leaves.LeavesConfig.skipUnnecessaryMobSpawningComputations ? flag2AndHasNaturalSpawn : flag2) && (!top.leavesmc.leaves.LeavesConfig.asyncMobSpawning || spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration // Leaves -skip unnecessary mob spawning computations | ||
- NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); | ||
+ NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1, peacefulModeSwitch); // Leaves - peaceful mode switch | ||
} | ||
// Leaves end - optimize mob spawning | ||
|
||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java | ||
index 9a5b31a3a8614ca2ff2d5bdb64dddccd70b22c3f..64fdfb3c124f8574fc0313b8fd764a5cd254b151 100644 | ||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java | ||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java | ||
@@ -133,6 +133,12 @@ public final class NaturalSpawner { | ||
} | ||
|
||
public static void spawnForChunk(ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnState info, boolean spawnAnimals, boolean spawnMonsters, boolean rareSpawn) { | ||
+ // Leaves start - peaceful mode switch | ||
+ spawnForChunk(world, chunk, info, spawnAnimals, spawnMonsters, rareSpawn, false); | ||
+ } | ||
+ | ||
+ public static void spawnForChunk(ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnState info, boolean spawnAnimals, boolean spawnMonsters, boolean rareSpawn, boolean peacefulModeSwitch) { | ||
+ // Leaves end - peaceful mode switch | ||
world.getProfiler().push("spawner"); | ||
world.timings.mobSpawn.startTiming(); // Spigot | ||
MobCategory[] aenumcreaturetype = NaturalSpawner.SPAWNING_CATEGORIES; | ||
@@ -142,6 +148,11 @@ public final class NaturalSpawner { | ||
|
||
for (int j = 0; j < i; ++j) { | ||
MobCategory enumcreaturetype = aenumcreaturetype[j]; | ||
+ // Leaves start - peaceful mode switch | ||
+ if (enumcreaturetype == MobCategory.MONSTER && peacefulModeSwitch) { | ||
+ continue; | ||
+ } | ||
+ // Leaves end - peaceful mode switch | ||
// CraftBukkit start - Use per-world spawn limits | ||
boolean spawnThisTick = true; | ||
int limit = enumcreaturetype.getMaxInstancesPerChunk(); | ||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java | ||
index 550dcb7d595221b221e4710890d8a3cad789fc07..7b576936c5a29f3714b2fc16c24e8cdec0d43f9e 100644 | ||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java | ||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java | ||
@@ -2300,6 +2300,18 @@ public class CraftWorld extends CraftRegionAccessor implements World { | ||
return CraftFeatureFlag.getFromNMS(this.getHandle().enabledFeatures()).stream().map(FeatureFlag.class::cast).collect(Collectors.toUnmodifiableSet()); | ||
} | ||
|
||
+ // Leaves start - unsupported settings | ||
+ @Override | ||
+ public void setPeacefulModeSwitchTick(int tick) { | ||
+ this.getHandle().chunkSource.peacefulModeSwitchTick = tick; | ||
+ } | ||
+ | ||
+ @Override | ||
+ public int getPeacefulModeSwitchTick(int tick) { | ||
+ return this.getHandle().chunkSource.peacefulModeSwitchTick; | ||
+ } | ||
+ // Leaves end - unsupported settings | ||
+ | ||
public void storeBukkitValues(CompoundTag c) { | ||
if (!this.persistentDataContainer.isEmpty()) { | ||
c.put("BukkitValues", this.persistentDataContainer.toTagCompound()); | ||
diff --git a/src/main/java/top/leavesmc/leaves/command/LeavesCommand.java b/src/main/java/top/leavesmc/leaves/command/LeavesCommand.java | ||
index 78d3df6a15057d42466c266226f308a070f560ac..06f5859cd04fe2147e37d61ab18e8fc0ff30769b 100644 | ||
--- a/src/main/java/top/leavesmc/leaves/command/LeavesCommand.java | ||
+++ b/src/main/java/top/leavesmc/leaves/command/LeavesCommand.java | ||
@@ -12,6 +12,7 @@ import org.bukkit.permissions.PermissionDefault; | ||
import org.bukkit.plugin.PluginManager; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
import org.jetbrains.annotations.NotNull; | ||
+import top.leavesmc.leaves.command.subcommands.PeacefulModeSwitchCommand; | ||
import top.leavesmc.leaves.command.subcommands.UpdateCommand; | ||
|
||
import java.util.ArrayList; | ||
@@ -33,6 +34,7 @@ public final class LeavesCommand extends Command { | ||
private static final Map<String, LeavesSubcommand> SUBCOMMANDS = Util.make(() -> { | ||
final Map<Set<String>, LeavesSubcommand> commands = new HashMap<>(); | ||
commands.put(Set.of("update"), new UpdateCommand()); | ||
+ commands.put(Set.of("peaceful"), new PeacefulModeSwitchCommand()); | ||
|
||
return commands.entrySet().stream() | ||
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue()))) | ||
diff --git a/src/main/java/top/leavesmc/leaves/command/subcommands/PeacefulModeSwitchCommand.java b/src/main/java/top/leavesmc/leaves/command/subcommands/PeacefulModeSwitchCommand.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..50c883ba689a51c1383e26ead3eb183c79b9a543 | ||
--- /dev/null | ||
+++ b/src/main/java/top/leavesmc/leaves/command/subcommands/PeacefulModeSwitchCommand.java | ||
@@ -0,0 +1,89 @@ | ||
+package top.leavesmc.leaves.command.subcommands; | ||
+ | ||
+import io.papermc.paper.command.CommandUtil; | ||
+import net.kyori.adventure.text.Component; | ||
+import net.kyori.adventure.text.JoinConfiguration; | ||
+import net.kyori.adventure.text.format.NamedTextColor; | ||
+import net.minecraft.server.level.ServerLevel; | ||
+import net.minecraft.world.entity.MobCategory; | ||
+import net.minecraft.world.level.NaturalSpawner; | ||
+import org.bukkit.Bukkit; | ||
+import org.bukkit.World; | ||
+import org.bukkit.command.CommandSender; | ||
+import org.bukkit.craftbukkit.CraftWorld; | ||
+import org.bukkit.entity.Player; | ||
+import top.leavesmc.leaves.command.LeavesSubcommand; | ||
+ | ||
+import java.util.ArrayList; | ||
+import java.util.Collections; | ||
+import java.util.List; | ||
+ | ||
+public class PeacefulModeSwitchCommand implements LeavesSubcommand { | ||
+ | ||
+ @Override | ||
+ public boolean execute(CommandSender sender, String subCommand, String[] args) { | ||
+ World world; | ||
+ if (args.length == 0) { | ||
+ if (sender instanceof Player player) { | ||
+ world = player.getWorld(); | ||
+ } else { | ||
+ sender.sendMessage(Component.text("Must specify a world! ex: '/leaves peaceful world'", NamedTextColor.RED)); | ||
+ return true; | ||
+ } | ||
+ } else { | ||
+ final String input = args[0]; | ||
+ final World inputWorld = Bukkit.getWorld(input); | ||
+ if (inputWorld == null) { | ||
+ sender.sendMessage(Component.text("'" + input + "' is not a valid world!", NamedTextColor.RED)); | ||
+ return true; | ||
+ } else { | ||
+ world = inputWorld; | ||
+ } | ||
+ } | ||
+ | ||
+ final ServerLevel level = ((CraftWorld) world).getHandle(); | ||
+ int chunks = 0; | ||
+ if (level.chunkSource.getLastSpawnState() != null) { | ||
+ chunks = level.chunkSource.getLastSpawnState().getSpawnableChunkCount(); | ||
+ } | ||
+ | ||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), | ||
+ Component.text("Peaceful Mode Switch for world: "), | ||
+ Component.text(world.getName(), NamedTextColor.AQUA) | ||
+ )); | ||
+ | ||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), | ||
+ Component.text("Refuses per "), | ||
+ Component.text(level.chunkSource.peacefulModeSwitchTick, level.chunkSource.peacefulModeSwitchTick > 0 ? NamedTextColor.AQUA : NamedTextColor.GRAY), | ||
+ Component.text(" tick") | ||
+ )); | ||
+ | ||
+ int count = level.chunkSource.peacefulModeSwitchCount; | ||
+ int limit = NaturalSpawner.globalLimitForCategory(level, MobCategory.MONSTER, chunks); | ||
+ NamedTextColor color = count >= limit ? NamedTextColor.AQUA : NamedTextColor.GRAY; | ||
+ | ||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), | ||
+ Component.text("Now count "), | ||
+ Component.text(count, color), | ||
+ Component.text("/", color), | ||
+ Component.text(limit, color) | ||
+ )); | ||
+ | ||
+ return true; | ||
+ } | ||
+ | ||
+ @Override | ||
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) { | ||
+ return CommandUtil.getListMatchingLast(sender, args, this.suggestPeacefulModeSwitch(args)); | ||
+ } | ||
+ | ||
+ private List<String> suggestPeacefulModeSwitch(final String[] args) { | ||
+ if (args.length == 1) { | ||
+ final List<String> worlds = new ArrayList<>(Bukkit.getWorlds().stream().map(World::getName).toList()); | ||
+ worlds.add("*"); | ||
+ return worlds; | ||
+ } | ||
+ | ||
+ return Collections.emptyList(); | ||
+ } | ||
+} |