mirror of
https://github.com/LeavesMC/Leaves.git
synced 2026-01-06 15:51:33 +00:00
228 lines
12 KiB
Diff
228 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
|
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 d021cd5b6136f0125076513977f430c6d4dd4f9f..f2b46b264762f9f58eebc37ab3c217d949625506 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -176,6 +176,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
// Paper end - chunk tick iteration optimisations
|
|
|
|
|
|
+ // Leaves start - peaceful mode switch
|
|
+ public int peacefulModeSwitchTick = org.leavesmc.leaves.LeavesConfig.modify.forcePeacefulMode;
|
|
+ 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
|
|
+
|
|
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory) {
|
|
this.level = world;
|
|
this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(world);
|
|
@@ -482,6 +488,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
if (!this.level.isDebug()) {
|
|
ProfilerFiller gameprofilerfiller = Profiler.get();
|
|
|
|
+ // 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
|
|
+
|
|
gameprofilerfiller.push("pollingChunks");
|
|
if (this.level.tickRateManager().runsNormally()) {
|
|
List<LevelChunk> list = this.tickingChunks;
|
|
@@ -579,6 +600,15 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
|
List list1;
|
|
|
|
+ // 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
|
|
+
|
|
if (flag && (this.spawnEnemies || this.spawnFriendlies)) {
|
|
// Paper start - PlayerNaturallySpawnCreaturesEvent
|
|
for (ServerPlayer entityPlayer : this.level.players()) {
|
|
@@ -590,7 +620,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
|
// Paper end - PlayerNaturallySpawnCreaturesEvent
|
|
boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
|
|
|
|
- list1 = NaturalSpawner.getFilteredSpawningCategories(spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1, this.level); // CraftBukkit
|
|
+ list1 = NaturalSpawner.getFilteredSpawningCategories(spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1, this.level, peacefulModeSwitch); // CraftBukkit Leaves start - peaceful mode switch
|
|
} else {
|
|
list1 = List.of();
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
index f817fd922ffcf857e8a5fc803b10421f640a8cd1..d5ece1268e7cab245a2ef2885bb83323d961bbd7 100644
|
|
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
|
@@ -131,7 +131,12 @@ public final class NaturalSpawner {
|
|
}
|
|
|
|
// CraftBukkit start - add server
|
|
+ // Leaves start - peaceful mode switch
|
|
public static List<MobCategory> getFilteredSpawningCategories(NaturalSpawner.SpawnState spawnercreature_d, boolean flag, boolean flag1, boolean flag2, ServerLevel worldserver) {
|
|
+ return getFilteredSpawningCategories(spawnercreature_d, flag, flag1, flag2, worldserver, false);
|
|
+ }
|
|
+ public static List<MobCategory> getFilteredSpawningCategories(NaturalSpawner.SpawnState spawnercreature_d, boolean flag, boolean flag1, boolean flag2, ServerLevel worldserver, boolean peacefulModeSwitch) {
|
|
+ // Leaves end - peaceful mode switch
|
|
LevelData worlddata = worldserver.getLevelData(); // CraftBukkit - Other mob type spawn tick rate
|
|
// CraftBukkit end
|
|
List<MobCategory> list = new ArrayList(NaturalSpawner.SPAWNING_CATEGORIES.length);
|
|
@@ -140,6 +145,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 df51d6d7909d407d8dcdbe1bfc5ca3a423005d5c..43a698baf88c7be00abbff517b95abc07ab67765 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
@@ -2410,6 +2410,18 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
|
|
// Paper - replace feature flag API
|
|
|
|
+ // Leaves start - unsupported settings
|
|
+ @Override
|
|
+ public void setPeacefulModeSwitchTick(int tick) {
|
|
+ this.getHandle().chunkSource.peacefulModeSwitchTick = tick;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public int getPeacefulModeSwitchTick() {
|
|
+ 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/org/leavesmc/leaves/command/LeavesCommand.java b/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java
|
|
index 41f4245f558f1c41ea84891b920f1d03dcb07066..92a8c3e4fc400988b3d984e7632a8149a2ce152e 100644
|
|
--- a/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java
|
|
@@ -33,6 +33,7 @@ public final class LeavesCommand extends Command {
|
|
final Map<Set<String>, LeavesSubcommand> commands = new HashMap<>();
|
|
commands.put(Set.of("config"), new ConfigCommand());
|
|
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/org/leavesmc/leaves/command/subcommands/PeacefulModeSwitchCommand.java b/src/main/java/org/leavesmc/leaves/command/subcommands/PeacefulModeSwitchCommand.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..1fe1d08cfb6caefc67cea27ac8fc188b8d6675c5
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/command/subcommands/PeacefulModeSwitchCommand.java
|
|
@@ -0,0 +1,87 @@
|
|
+package org.leavesmc.leaves.command.subcommands;
|
|
+
|
|
+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 org.leavesmc.leaves.command.LeavesCommandUtil;
|
|
+import org.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 LeavesCommandUtil.getListMatchingLast(sender, args, this.suggestPeacefulModeSwitch(args));
|
|
+ }
|
|
+
|
|
+ private List<String> suggestPeacefulModeSwitch(final String[] args) {
|
|
+ if (args.length == 1) {
|
|
+ return new ArrayList<>(Bukkit.getWorlds().stream().map(World::getName).toList());
|
|
+ }
|
|
+
|
|
+ return Collections.emptyList();
|
|
+ }
|
|
+}
|