mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-29 19:59:18 +00:00
apply rest of patches
This commit is contained in:
@@ -53,7 +53,7 @@ index a43e5190c0f9ae14ccecccd5b58dc0e17f18b0a1..06ffba13f211851e8f6d630a72b41474
|
||||
|
||||
private boolean canMerge(ExperienceOrb orb) {
|
||||
- return orb != this && canMerge(orb, this.getId(), this.value);
|
||||
+ return org.bxteam.divinemc.DivineConfig.clumpOrbs ? orb.isAlive() && !this.is(orb) : orb != this && ExperienceOrb.canMerge(orb, this.getId(), this.value); // DivineMC - Clump experience orbs
|
||||
+ return org.bxteam.divinemc.DivineConfig.clumpOrbs ? orb.isAlive() && !this.is(orb) : orb != this && canMerge(orb, this.getId(), this.value); // DivineMC - Clump experience orbs
|
||||
}
|
||||
|
||||
private static boolean canMerge(ExperienceOrb orb, int amount, int other) {
|
||||
@@ -1,75 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 11 Jan 2025 22:22:01 +0300
|
||||
Subject: [PATCH] Rebrand
|
||||
|
||||
|
||||
diff --git a/net/minecraft/CrashReport.java b/net/minecraft/CrashReport.java
|
||||
index 394443d00e661715439be1e56dddc129947699a4..480ad57a6b7b74e6b83e9c6ceb69ea1feacca106 100644
|
||||
--- a/net/minecraft/CrashReport.java
|
||||
+++ b/net/minecraft/CrashReport.java
|
||||
@@ -30,7 +30,7 @@ public class CrashReport {
|
||||
private boolean trackingStackTrace = true;
|
||||
private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0];
|
||||
private final SystemReport systemReport = new SystemReport();
|
||||
- private List<String> extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER! REPORT TO PURPUR INSTEAD!", ""); // Purpur - Rebrand
|
||||
+ private List<String> extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER! REPORT TO DIVINEMC INSTEAD!", ""); // DivineMC - Rebrand
|
||||
|
||||
public CrashReport(String title, Throwable exception) {
|
||||
io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception); // Paper
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 781030cb2e0316151c20351f04347c8db63f43e1..6bb8afb3b0e92c374474c92fa44dc7b80af0bd73 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1182,6 +1182,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
|
||||
protected void runServer() {
|
||||
try {
|
||||
+ org.bxteam.divinemc.spark.ThreadDumperRegistry.REGISTRY.add(Thread.currentThread().getName()); // DivineMC
|
||||
if (!this.initServer()) {
|
||||
throw new IllegalStateException("Failed to initialize server");
|
||||
}
|
||||
diff --git a/net/minecraft/server/gui/MinecraftServerGui.java b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
index 614c7d9f673c926562acc8fa3b3788623900db41..33456c7c106abbddf743e1203a6e8122cf10b797 100644
|
||||
--- a/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
+++ b/net/minecraft/server/gui/MinecraftServerGui.java
|
||||
@@ -51,7 +51,7 @@ public class MinecraftServerGui extends JComponent {
|
||||
} catch (Exception var3) {
|
||||
}
|
||||
|
||||
- final JFrame jFrame = new JFrame("Purpur Minecraft server"); // Purpur - Improve GUI
|
||||
+ final JFrame jFrame = new JFrame("DivineMC Minecraft server"); // Purpur - Improve GUI // DivineMC - Rebrand
|
||||
final MinecraftServerGui minecraftServerGui = new MinecraftServerGui(server);
|
||||
jFrame.setDefaultCloseOperation(2);
|
||||
jFrame.add(minecraftServerGui);
|
||||
@@ -59,7 +59,7 @@ public class MinecraftServerGui extends JComponent {
|
||||
jFrame.setLocationRelativeTo(null);
|
||||
jFrame.setVisible(true);
|
||||
// Paper start - Improve ServerGUI
|
||||
- jFrame.setName("Purpur Minecraft server"); // Purpur - Improve GUI
|
||||
+ jFrame.setName("DivineMC Minecraft server"); // Purpur - Improve GUI // DivineMC - Rebrand
|
||||
try {
|
||||
jFrame.setIconImage(javax.imageio.ImageIO.read(java.util.Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png"))));
|
||||
} catch (java.io.IOException ignore) {
|
||||
@@ -69,7 +69,7 @@ public class MinecraftServerGui extends JComponent {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent event) {
|
||||
if (!minecraftServerGui.isClosing.getAndSet(true)) {
|
||||
- jFrame.setTitle("Purpur Minecraft server - shutting down!"); // Purpur - Improve GUI
|
||||
+ jFrame.setTitle("DivineMC Minecraft server - shutting down!"); // Purpur - Improve GUI // DivineMC - Rebrand
|
||||
server.halt(true);
|
||||
minecraftServerGui.runFinalizers();
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index 80ed0e4b8c867d031413b4140e52af1342fdcb54..6ebd1300c2561116b83cb2472ac7939ead36d576 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -283,7 +283,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
// Paper start
|
||||
private static void printOversizedLog(String msg, Path file, int x, int z) {
|
||||
- org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // Purpur - Rebrand
|
||||
+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO DIVINEMC - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // DivineMC - Rebrand
|
||||
}
|
||||
|
||||
private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
|
||||
@@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Mon, 27 Jan 2025 20:22:52 +0300
|
||||
Subject: [PATCH] Configuration
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 1d9bf122c4c32c486a33d846c95afcab12560fd7..61eeec6a0d789e5e44abdeb5826d7ee2307301ba 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -218,6 +218,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
}
|
||||
org.purpurmc.purpur.PurpurConfig.registerCommands();
|
||||
// Purpur end - Configurable void damage height and damage
|
||||
+ // DivineMC start - Configuration
|
||||
+ try {
|
||||
+ org.bxteam.divinemc.DivineConfig.init((java.io.File) options.valueOf("divinemc-settings"));
|
||||
+ } catch (Exception e) {
|
||||
+ DedicatedServer.LOGGER.error("Unable to load server configuration", e);
|
||||
+ return false;
|
||||
+ }
|
||||
+ org.bxteam.divinemc.command.DivineCommands.registerCommands(this);
|
||||
+ // DivineMC end - Configuration
|
||||
// Paper start - initialize global and world-defaults configuration
|
||||
this.paperConfigurations.initializeGlobalConfiguration(this.registryAccess());
|
||||
this.paperConfigurations.initializeWorldDefaultsConfiguration(this.registryAccess());
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 0fe8f4601eedfa68c38ebadc7847ba7a07ff6fb6..b4c2602ecf6b943ab022866231f74b850269af8f 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -171,6 +171,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
|
||||
public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
|
||||
public final org.purpurmc.purpur.PurpurWorldConfig purpurConfig; // Purpur - Purpur config files
|
||||
+ public final org.bxteam.divinemc.DivineWorldConfig divineConfig; // DivineMC - Configuration
|
||||
public static BlockPos lastPhysicsProblem; // Spigot
|
||||
private org.spigotmc.TickLimiter entityLimiter;
|
||||
private org.spigotmc.TickLimiter tileLimiter;
|
||||
@@ -898,6 +899,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot
|
||||
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
|
||||
this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName(), env); // Purpur - Purpur config files
|
||||
+ // DivineMC start - Configuration
|
||||
+ try {
|
||||
+ this.divineConfig = new org.bxteam.divinemc.DivineWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName(), env);
|
||||
+ } catch (java.io.IOException e) {
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.error("Failed to load DivineMC configuration for world '{}'", ((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName(), e);
|
||||
+ throw new RuntimeException(e);
|
||||
+ }
|
||||
+ // DivineMC end - Configuration
|
||||
this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur - Add adjustable breeding cooldown to config
|
||||
this.generator = gen;
|
||||
this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,433 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Tue, 28 Jan 2025 00:54:57 +0300
|
||||
Subject: [PATCH] Implement Secure Seed
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/plasmoapp/matter
|
||||
|
||||
diff --git a/net/minecraft/server/commands/SeedCommand.java b/net/minecraft/server/commands/SeedCommand.java
|
||||
index a65affc41a4fc299bc2281f0f53f2e075633899d..7284c984f9309d4a862fe6f89df993c9a6a9efa6 100644
|
||||
--- a/net/minecraft/server/commands/SeedCommand.java
|
||||
+++ b/net/minecraft/server/commands/SeedCommand.java
|
||||
@@ -12,6 +12,17 @@ public class SeedCommand {
|
||||
long seed = context.getSource().getLevel().getSeed();
|
||||
Component component = ComponentUtils.copyOnClickText(String.valueOf(seed));
|
||||
context.getSource().sendSuccess(() -> Component.translatable("commands.seed.success", component), false);
|
||||
+
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ su.plo.matter.Globals.setupGlobals(context.getSource().getLevel());
|
||||
+ String seedStr = su.plo.matter.Globals.seedToString(su.plo.matter.Globals.worldSeed);
|
||||
+ Component featureSeedComponent = ComponentUtils.copyOnClickText(seedStr);
|
||||
+
|
||||
+ context.getSource().sendSuccess(() -> Component.translatable(("Feature seed: %s"), featureSeedComponent), false);
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
+
|
||||
return (int)seed;
|
||||
}));
|
||||
}
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServerProperties.java b/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
index 5748658abf0b90812005ae9d426df92daf5532f0..8b4b91be368b4195326eeb1c714d713a95f28d76 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java
|
||||
@@ -114,7 +114,17 @@ public class DedicatedServerProperties extends Settings<DedicatedServerPropertie
|
||||
String string = this.get("level-seed", "");
|
||||
boolean flag = this.get("generate-structures", true);
|
||||
long l = WorldOptions.parseSeed(string).orElse(WorldOptions.randomSeed());
|
||||
- this.worldOptions = new WorldOptions(l, flag, false);
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ String featureSeedStr = this.get("feature-level-seed", "");
|
||||
+ long[] featureSeed = su.plo.matter.Globals.parseSeed(featureSeedStr)
|
||||
+ .orElse(su.plo.matter.Globals.createRandomWorldSeed());
|
||||
+
|
||||
+ this.worldOptions = new WorldOptions(l, featureSeed, flag, false);
|
||||
+ } else {
|
||||
+ this.worldOptions = new WorldOptions(l, flag, false);
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
this.worldDimensionData = new DedicatedServerProperties.WorldDimensionData(
|
||||
this.get("generator-settings", property -> GsonHelper.parse(!property.isEmpty() ? property : "{}"), new JsonObject()),
|
||||
this.get("level-type", property -> property.toLowerCase(Locale.ROOT), WorldPresets.NORMAL.location().toString())
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 8055b8552b40160732953b15876dda7983890d06..ab30af9cd58ff7310e05be87b08f42bacf69e11e 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -618,6 +618,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
|
||||
public ChunkGenerator getGenerator() {
|
||||
+ su.plo.matter.Globals.setupGlobals(level); // DivineMC - Implement Secure Seed
|
||||
return this.chunkMap.generator();
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 3980e0dfb08a357384ea33670fb282a26a598f6e..9afd448ede87c9192dc576f66e08676a68b34d98 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -632,6 +632,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
chunkGenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkGenerator, gen);
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ su.plo.matter.Globals.setupGlobals(this); // DivineMC - Implement Secure Seed
|
||||
boolean flag = server.forceSynchronousWrites();
|
||||
DataFixer fixerUpper = server.getFixerUpper();
|
||||
// Paper - rewrite chunk system
|
||||
diff --git a/net/minecraft/world/entity/monster/Slime.java b/net/minecraft/world/entity/monster/Slime.java
|
||||
index 240a54b210e23d5b79e6bcaf3806aa454668135d..66dffb8a2c6725ea2502b498044b854f043f3c73 100644
|
||||
--- a/net/minecraft/world/entity/monster/Slime.java
|
||||
+++ b/net/minecraft/world/entity/monster/Slime.java
|
||||
@@ -423,8 +423,13 @@ public class Slime extends Mob implements Enemy {
|
||||
return false;
|
||||
}
|
||||
|
||||
- ChunkPos chunkPos = new ChunkPos(pos);
|
||||
- boolean flag = level.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel) level).getSeed(), level.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
|
||||
+ ChunkPos chunkPos = new ChunkPos(pos);
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ boolean isSlimeChunk = org.bxteam.divinemc.DivineConfig.enableSecureSeed
|
||||
+ ? level.getChunk(chunkPos.x, chunkPos.z).isSlimeChunk()
|
||||
+ : WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel) level).getSeed(), level.getMinecraftWorld().spigotConfig.slimeSeed).nextInt(10) == 0; // Spigot // Paper
|
||||
+ boolean flag = level.getMinecraftWorld().paperConfig().entities.spawning.allChunksAreSlimeChunks || isSlimeChunk;
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
// Paper start - Replace rules for Height in Slime Chunks
|
||||
final double maxHeightSlimeChunk = level.getMinecraftWorld().paperConfig().entities.spawning.slimeSpawnHeight.slimeChunk.maximum;
|
||||
if (random.nextInt(10) == 0 && flag && pos.getY() < maxHeightSlimeChunk) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
index 6d565b52552534ce9cacfc35ad1bf4adcb69eac3..80a0f5524e91e55d716e93c29e199d9816b0072a 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
@@ -82,6 +82,10 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
|
||||
public final Map<BlockPos, BlockEntity> blockEntities = new Object2ObjectOpenHashMap<>();
|
||||
protected final LevelHeightAccessor levelHeightAccessor;
|
||||
protected final LevelChunkSection[] sections;
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ private boolean slimeChunk;
|
||||
+ private boolean hasComputedSlimeChunk;
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
// CraftBukkit start - SPIGOT-6814: move to IChunkAccess to account for 1.17 to 1.18 chunk upgrading.
|
||||
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(ChunkAccess.DATA_TYPE_REGISTRY);
|
||||
@@ -191,6 +195,17 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
|
||||
return GameEventListenerRegistry.NOOP;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ public boolean isSlimeChunk() {
|
||||
+ if (!hasComputedSlimeChunk) {
|
||||
+ hasComputedSlimeChunk = true;
|
||||
+ slimeChunk = su.plo.matter.WorldgenCryptoRandom.seedSlimeChunk(chunkPos.x, chunkPos.z).nextInt(10) == 0;
|
||||
+ }
|
||||
+
|
||||
+ return slimeChunk;
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
+
|
||||
public abstract BlockState getBlockState(final int x, final int y, final int z); // Paper
|
||||
@Nullable
|
||||
public abstract BlockState setBlockState(BlockPos pos, BlockState state, boolean isMoving);
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index 6ed51cf42b5864194d671b5b56f5b9bdf0291dc0..7e0b602e9fd9e3b3f60014ab179b3a82e3bf5c2a 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -343,7 +343,11 @@ public abstract class ChunkGenerator {
|
||||
Registry<Structure> registry = level.registryAccess().lookupOrThrow(Registries.STRUCTURE);
|
||||
Map<Integer, List<Structure>> map = registry.stream().collect(Collectors.groupingBy(structure1 -> structure1.step().ordinal()));
|
||||
List<FeatureSorter.StepFeatureData> list = this.featuresPerStep.get();
|
||||
- WorldgenRandom worldgenRandom = new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ WorldgenRandom worldgenRandom = org.bxteam.divinemc.DivineConfig.enableSecureSeed
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(blockPos.getX(), blockPos.getZ(), su.plo.matter.Globals.Salt.UNDEFINED, 0)
|
||||
+ : new WorldgenRandom(new XoroshiroRandomSource(RandomSupport.generateUniqueSeed()));
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
long l = worldgenRandom.setDecorationSeed(level.getSeed(), blockPos.getX(), blockPos.getZ());
|
||||
Set<Holder<Biome>> set = new ObjectArraySet<>();
|
||||
ChunkPos.rangeClosed(sectionPos.chunk(), 1).forEach(chunkPos -> {
|
||||
@@ -556,8 +560,18 @@ public abstract class ChunkGenerator {
|
||||
} else {
|
||||
ArrayList<StructureSet.StructureSelectionEntry> list1 = new ArrayList<>(list.size());
|
||||
list1.addAll(list);
|
||||
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- worldgenRandom.setLargeFeatureSeed(structureState.getLevelSeed(), pos.x, pos.z);
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ WorldgenRandom worldgenRandom;
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ worldgenRandom = new su.plo.matter.WorldgenCryptoRandom(
|
||||
+ pos.x, pos.z, su.plo.matter.Globals.Salt.GENERATE_FEATURE, 0
|
||||
+ );
|
||||
+ } else {
|
||||
+ worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+
|
||||
+ worldgenRandom.setLargeFeatureSeed(structureState.getLevelSeed(), pos.x, pos.z);
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
int i = 0;
|
||||
|
||||
for (StructureSet.StructureSelectionEntry structureSelectionEntry1 : list1) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
index 619b98e42e254c0c260c171a26a2472ddf59b885..a3093ef1b47544f2eb02d366040526697dafc8db 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkGeneratorStructureState.java
|
||||
@@ -205,14 +205,21 @@ public class ChunkGeneratorStructureState {
|
||||
List<CompletableFuture<ChunkPos>> list = new ArrayList<>(count);
|
||||
int spread = placement.spread();
|
||||
HolderSet<Biome> holderSet = placement.preferredBiomes();
|
||||
- RandomSource randomSource = RandomSource.create();
|
||||
- // Paper start - Add missing structure set seed configs
|
||||
- if (this.conf.strongholdSeed != null && structureSet.is(net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS)) {
|
||||
- randomSource.setSeed(this.conf.strongholdSeed);
|
||||
- } else {
|
||||
- // Paper end - Add missing structure set seed configs
|
||||
- randomSource.setSeed(this.concentricRingsSeed);
|
||||
- } // Paper - Add missing structure set seed configs
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ RandomSource randomSource = org.bxteam.divinemc.DivineConfig.enableSecureSeed
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.STRONGHOLDS, 0)
|
||||
+ : RandomSource.create();
|
||||
+
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ // Paper start - Add missing structure set seed configs
|
||||
+ if (this.conf.strongholdSeed != null && structureSet.is(net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS)) {
|
||||
+ randomSource.setSeed(this.conf.strongholdSeed);
|
||||
+ } else {
|
||||
+ // Paper end - Add missing structure set seed configs
|
||||
+ randomSource.setSeed(this.concentricRingsSeed);
|
||||
+ } // Paper - Add missing structure set seed configs
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
double d = randomSource.nextDouble() * Math.PI * 2.0;
|
||||
int i = 0;
|
||||
int i1 = 0;
|
||||
diff --git a/net/minecraft/world/level/chunk/status/ChunkStep.java b/net/minecraft/world/level/chunk/status/ChunkStep.java
|
||||
index b8348976e80578d9eff64eea68c04c603fed49ad..9494e559113798fe451a6d0226be3ae0449021dc 100644
|
||||
--- a/net/minecraft/world/level/chunk/status/ChunkStep.java
|
||||
+++ b/net/minecraft/world/level/chunk/status/ChunkStep.java
|
||||
@@ -60,6 +60,7 @@ public final class ChunkStep implements ca.spottedleaf.moonrise.patches.chunk_sy
|
||||
}
|
||||
|
||||
public CompletableFuture<ChunkAccess> apply(WorldGenContext worldGenContext, StaticCache2D<GenerationChunkHolder> cache, ChunkAccess chunk) {
|
||||
+ su.plo.matter.Globals.setupGlobals(worldGenContext.level()); // DivineMC - Implement Secure Seed
|
||||
if (chunk.getPersistedStatus().isBefore(this.targetStatus)) {
|
||||
ProfiledDuration profiledDuration = JvmProfiler.INSTANCE
|
||||
.onChunkGenerate(chunk.getPos(), worldGenContext.level().dimension(), this.targetStatus.getName());
|
||||
diff --git a/net/minecraft/world/level/levelgen/WorldOptions.java b/net/minecraft/world/level/levelgen/WorldOptions.java
|
||||
index c92508741439a8d0d833ea02d0104416adb83c92..630f6c409db349819fc5fd19a3d78fadb4cfb6d6 100644
|
||||
--- a/net/minecraft/world/level/levelgen/WorldOptions.java
|
||||
+++ b/net/minecraft/world/level/levelgen/WorldOptions.java
|
||||
@@ -9,17 +9,28 @@ import net.minecraft.util.RandomSource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class WorldOptions {
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ private static final boolean isSecureSeedEnabled = org.bxteam.divinemc.DivineConfig.enableSecureSeed;
|
||||
public static final MapCodec<WorldOptions> CODEC = RecordCodecBuilder.mapCodec(
|
||||
- instance -> instance.group(
|
||||
+ instance -> isSecureSeedEnabled
|
||||
+ ? instance.group(
|
||||
Codec.LONG.fieldOf("seed").stable().forGetter(WorldOptions::seed),
|
||||
+ Codec.LONG_STREAM.fieldOf("feature_seed").stable().forGetter(WorldOptions::featureSeedStream),
|
||||
Codec.BOOL.fieldOf("generate_features").orElse(true).stable().forGetter(WorldOptions::generateStructures),
|
||||
Codec.BOOL.fieldOf("bonus_chest").orElse(false).stable().forGetter(WorldOptions::generateBonusChest),
|
||||
- Codec.STRING.lenientOptionalFieldOf("legacy_custom_options").stable().forGetter(worldOptions -> worldOptions.legacyCustomOptions)
|
||||
- )
|
||||
- .apply(instance, instance.stable(WorldOptions::new))
|
||||
+ Codec.STRING.lenientOptionalFieldOf("legacy_custom_options").stable().forGetter(generatorOptions -> generatorOptions.legacyCustomOptions)).apply(instance, instance.stable(WorldOptions::new))
|
||||
+ : instance.group(
|
||||
+ Codec.LONG.fieldOf("seed").stable().forGetter(WorldOptions::seed),
|
||||
+ Codec.BOOL.fieldOf("generate_features").orElse(true).stable().forGetter(WorldOptions::generateStructures),
|
||||
+ Codec.BOOL.fieldOf("bonus_chest").orElse(false).stable().forGetter(WorldOptions::generateBonusChest),
|
||||
+ Codec.STRING.lenientOptionalFieldOf("legacy_custom_options").stable().forGetter(worldOptions -> worldOptions.legacyCustomOptions)).apply(instance, instance.stable(WorldOptions::new))
|
||||
);
|
||||
- public static final WorldOptions DEMO_OPTIONS = new WorldOptions("North Carolina".hashCode(), true, true);
|
||||
+ public static final WorldOptions DEMO_OPTIONS = isSecureSeedEnabled
|
||||
+ ? new WorldOptions("North Carolina".hashCode(), su.plo.matter.Globals.createRandomWorldSeed(), true, true)
|
||||
+ : new WorldOptions("North Carolina".hashCode(), true, true);
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
private final long seed;
|
||||
+ private long[] featureSeed = su.plo.matter.Globals.createRandomWorldSeed(); // DivineMC - Implement Secure Seed
|
||||
private final boolean generateStructures;
|
||||
private final boolean generateBonusChest;
|
||||
private final Optional<String> legacyCustomOptions;
|
||||
@@ -28,9 +39,21 @@ public class WorldOptions {
|
||||
this(seed, generateStructures, generateBonusChest, Optional.empty());
|
||||
}
|
||||
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ public WorldOptions(long seed, long[] featureSeed, boolean generateStructures, boolean bonusChest) {
|
||||
+ this(seed, featureSeed, generateStructures, bonusChest, Optional.empty());
|
||||
+ }
|
||||
+
|
||||
public static WorldOptions defaultWithRandomSeed() {
|
||||
- return new WorldOptions(randomSeed(), true, false);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(randomSeed(), su.plo.matter.Globals.createRandomWorldSeed(), true, false)
|
||||
+ : new WorldOptions(randomSeed(), true, false);
|
||||
+ }
|
||||
+
|
||||
+ private WorldOptions(long seed, java.util.stream.LongStream featureSeed, boolean generateStructures, boolean bonusChest, Optional<String> legacyCustomOptions) {
|
||||
+ this(seed, featureSeed.toArray(), generateStructures, bonusChest, legacyCustomOptions);
|
||||
}
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
|
||||
public static WorldOptions testWorldWithRandomSeed() {
|
||||
return new WorldOptions(randomSeed(), false, false);
|
||||
@@ -43,10 +66,27 @@ public class WorldOptions {
|
||||
this.legacyCustomOptions = legacyCustomOptions;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ private WorldOptions(long seed, long[] featureSeed, boolean generateStructures, boolean bonusChest, Optional<String> legacyCustomOptions) {
|
||||
+ this(seed, generateStructures, bonusChest, legacyCustomOptions);
|
||||
+ this.featureSeed = featureSeed;
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
+
|
||||
public long seed() {
|
||||
return this.seed;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ public long[] featureSeed() {
|
||||
+ return this.featureSeed;
|
||||
+ }
|
||||
+
|
||||
+ public java.util.stream.LongStream featureSeedStream() {
|
||||
+ return java.util.stream.LongStream.of(this.featureSeed);
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
+
|
||||
public boolean generateStructures() {
|
||||
return this.generateStructures;
|
||||
}
|
||||
@@ -59,17 +99,25 @@ public class WorldOptions {
|
||||
return this.legacyCustomOptions.isPresent();
|
||||
}
|
||||
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
public WorldOptions withBonusChest(boolean generateBonusChest) {
|
||||
- return new WorldOptions(this.seed, this.generateStructures, generateBonusChest, this.legacyCustomOptions);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(this.seed, this.featureSeed, this.generateStructures, generateBonusChest, this.legacyCustomOptions)
|
||||
+ : new WorldOptions(this.seed, this.generateStructures, generateBonusChest, this.legacyCustomOptions);
|
||||
}
|
||||
|
||||
public WorldOptions withStructures(boolean generateStructures) {
|
||||
- return new WorldOptions(this.seed, generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(this.seed, this.featureSeed, generateStructures, this.generateBonusChest, this.legacyCustomOptions)
|
||||
+ : new WorldOptions(this.seed, generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
}
|
||||
|
||||
public WorldOptions withSeed(OptionalLong seed) {
|
||||
- return new WorldOptions(seed.orElse(randomSeed()), this.generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
+ return isSecureSeedEnabled
|
||||
+ ? new WorldOptions(seed.orElse(randomSeed()), su.plo.matter.Globals.createRandomWorldSeed(), this.generateStructures, this.generateBonusChest, this.legacyCustomOptions)
|
||||
+ : new WorldOptions(seed.orElse(randomSeed()), this.generateStructures, this.generateBonusChest, this.legacyCustomOptions);
|
||||
}
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
|
||||
public static OptionalLong parseSeed(String seed) {
|
||||
seed = seed.trim();
|
||||
diff --git a/net/minecraft/world/level/levelgen/feature/GeodeFeature.java b/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
|
||||
index 38475f6975533909924c8d54f438cf43cdfe31a3..6759df026a29810021ddb37f3ddb62382b83a94e 100644
|
||||
--- a/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
|
||||
+++ b/net/minecraft/world/level/levelgen/feature/GeodeFeature.java
|
||||
@@ -41,7 +41,11 @@ public class GeodeFeature extends Feature<GeodeConfiguration> {
|
||||
int i1 = geodeConfiguration.maxGenOffset;
|
||||
List<Pair<BlockPos, Integer>> list = Lists.newLinkedList();
|
||||
int i2 = geodeConfiguration.distributionPoints.sample(randomSource);
|
||||
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(worldGenLevel.getSeed()));
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ WorldgenRandom worldgenRandom = org.bxteam.divinemc.DivineConfig.enableSecureSeed
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(0, 0, su.plo.matter.Globals.Salt.GEODE_FEATURE, 0)
|
||||
+ : new WorldgenRandom(new LegacyRandomSource(worldGenLevel.getSeed()));
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
NormalNoise normalNoise = NormalNoise.create(worldgenRandom, -4, 1.0);
|
||||
List<BlockPos> list1 = Lists.newLinkedList();
|
||||
double d = (double)i2 / geodeConfiguration.outerWallDistance.getMaxValue();
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/Structure.java b/net/minecraft/world/level/levelgen/structure/Structure.java
|
||||
index 8328e864c72b7a358d6bb1f33459b8c4df2ecb1a..7c35949c9a2f102e9da246fd5bf81d9e14eb36ca 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/Structure.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/Structure.java
|
||||
@@ -249,6 +249,14 @@ public abstract class Structure {
|
||||
}
|
||||
|
||||
private static WorldgenRandom makeRandom(long seed, ChunkPos chunkPos) {
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ return new su.plo.matter.WorldgenCryptoRandom(
|
||||
+ chunkPos.x, chunkPos.z, su.plo.matter.Globals.Salt.GENERATE_FEATURE, seed
|
||||
+ );
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
+
|
||||
WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
worldgenRandom.setLargeFeatureSeed(seed, chunkPos.x, chunkPos.z);
|
||||
return worldgenRandom;
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java b/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
|
||||
index ee0d9dddb36b6879fa113299e24f1aa3b2b151cc..f01d96895ab348971fb31b614026fb3d106e9a3e 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/placement/RandomSpreadStructurePlacement.java
|
||||
@@ -67,8 +67,17 @@ public class RandomSpreadStructurePlacement extends StructurePlacement {
|
||||
public ChunkPos getPotentialStructureChunk(long seed, int regionX, int regionZ) {
|
||||
int i = Math.floorDiv(regionX, this.spacing);
|
||||
int i1 = Math.floorDiv(regionZ, this.spacing);
|
||||
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- worldgenRandom.setLargeFeatureWithSalt(seed, i, i1, this.salt());
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ WorldgenRandom worldgenRandom;
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ worldgenRandom = new su.plo.matter.WorldgenCryptoRandom(
|
||||
+ i, i1, su.plo.matter.Globals.Salt.POTENTIONAL_FEATURE, this.salt
|
||||
+ );
|
||||
+ } else {
|
||||
+ worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ worldgenRandom.setLargeFeatureWithSalt(seed, i, i1, this.salt());
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
int i2 = this.spacing - this.separation;
|
||||
int i3 = this.spreadType.evaluate(worldgenRandom, i2);
|
||||
int i4 = this.spreadType.evaluate(worldgenRandom, i2);
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java b/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
index 670335a7bbfbc9da64c389977498c22dfcd03251..7174a9767cbc94544be81c74d6468f3f73386edc 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java
|
||||
@@ -118,8 +118,17 @@ public abstract class StructurePlacement {
|
||||
public abstract StructurePlacementType<?> type();
|
||||
|
||||
private static boolean probabilityReducer(long levelSeed, int regionX, int regionZ, int salt, float probability, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - Add missing structure set seed configs; ignore here
|
||||
- WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
- worldgenRandom.setLargeFeatureWithSalt(levelSeed, regionX, regionZ, salt);
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ WorldgenRandom worldgenRandom;
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableSecureSeed) {
|
||||
+ worldgenRandom = new su.plo.matter.WorldgenCryptoRandom(
|
||||
+ regionX, regionZ, su.plo.matter.Globals.Salt.UNDEFINED, salt
|
||||
+ );
|
||||
+ } else {
|
||||
+ worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L));
|
||||
+ worldgenRandom.setLargeFeatureWithSalt(levelSeed, salt, regionX, regionZ);
|
||||
+ }
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
return worldgenRandom.nextFloat() < probability;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java b/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
index eb85edaa3b7fab4f11545b0fa8bfea882dedb67d..63143ceec98f7a84ec4064d05e8f88c11200172f 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
@@ -64,7 +64,11 @@ public class JigsawPlacement {
|
||||
ChunkGenerator chunkGenerator = context.chunkGenerator();
|
||||
StructureTemplateManager structureTemplateManager = context.structureTemplateManager();
|
||||
LevelHeightAccessor levelHeightAccessor = context.heightAccessor();
|
||||
- WorldgenRandom worldgenRandom = context.random();
|
||||
+ // DivineMC start - Implement Secure Seed
|
||||
+ WorldgenRandom worldgenRandom = org.bxteam.divinemc.DivineConfig.enableSecureSeed
|
||||
+ ? new su.plo.matter.WorldgenCryptoRandom(context.chunkPos().x, context.chunkPos().z, su.plo.matter.Globals.Salt.JIGSAW_PLACEMENT, 0)
|
||||
+ : context.random();
|
||||
+ // DivineMC end - Implement Secure Seed
|
||||
Registry<StructureTemplatePool> registry = registryAccess.lookupOrThrow(Registries.TEMPLATE_POOL);
|
||||
Rotation random = Rotation.getRandom(worldgenRandom);
|
||||
StructureTemplatePool structureTemplatePool = startPool.unwrapKey()
|
||||
@@ -1,813 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Tue, 28 Jan 2025 01:04:55 +0300
|
||||
Subject: [PATCH] Async Pathfinding
|
||||
|
||||
Original code by Bloom-host, licensed under GPL v3
|
||||
You can find the original code on https://github.com/Bloom-host/Petal
|
||||
|
||||
Makes most pathfinding-related work happen asynchronously
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
index 67cbf9f5760fae5db6f31e64095cd1b6be6ade8e..7ad36864d700f3012a3791bf3814465e5e9deffa 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
|
||||
@@ -94,21 +94,18 @@ public class AcquirePoi {
|
||||
}
|
||||
}
|
||||
// Paper end - optimise POI access
|
||||
- Path path = findPathToPois(mob, set);
|
||||
- if (path != null && path.canReach()) {
|
||||
- BlockPos target = path.getTarget();
|
||||
- poiManager.getType(target).ifPresent(holder -> {
|
||||
- poiManager.take(acquirablePois, (holder1, blockPos) -> blockPos.equals(target), target, 1);
|
||||
- memoryAccessor.set(GlobalPos.of(level.dimension(), target));
|
||||
- entityEventId.ifPresent(id -> level.broadcastEntityEvent(mob, id));
|
||||
- map.clear();
|
||||
- DebugPackets.sendPoiTicketCountPacket(level, target);
|
||||
+ // DivineMC start - Async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ Path possiblePath = findPathToPois(mob, set);
|
||||
+
|
||||
+ org.bxteam.divinemc.entity.pathfinding.AsyncPathProcessor.awaitProcessing(possiblePath, path -> {
|
||||
+ processPath(acquirablePois, entityEventId, (Long2ObjectMap<JitteredLinearRetry>) map, memoryAccessor, level, mob, time, poiManager, set, path);
|
||||
});
|
||||
} else {
|
||||
- for (Pair<Holder<PoiType>, BlockPos> pair : set) {
|
||||
- map.computeIfAbsent(pair.getSecond().asLong(), l -> new AcquirePoi.JitteredLinearRetry(level.random, time));
|
||||
- }
|
||||
+ Path path = findPathToPois(mob, set);
|
||||
+ processPath(acquirablePois, entityEventId, (Long2ObjectMap<JitteredLinearRetry>) map, memoryAccessor, level, mob, time, poiManager, set, path);
|
||||
}
|
||||
+ // DivineMC end - Async path processing
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -120,6 +117,34 @@ public class AcquirePoi {
|
||||
: BehaviorBuilder.create(instance -> instance.group(instance.absent(existingAbsentMemory)).apply(instance, memoryAccessor -> oneShot));
|
||||
}
|
||||
|
||||
+ // DivineMC start - Async path processing
|
||||
+ private static void processPath(Predicate<Holder<PoiType>> acquirablePois,
|
||||
+ Optional<Byte> entityEventId,
|
||||
+ Long2ObjectMap<JitteredLinearRetry> map,
|
||||
+ net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor<com.mojang.datafixers.kinds.Const.Mu<com.mojang.datafixers.util.Unit>, GlobalPos> memoryAccessor,
|
||||
+ ServerLevel level,
|
||||
+ PathfinderMob mob,
|
||||
+ long time,
|
||||
+ PoiManager poiManager,
|
||||
+ Set<Pair<Holder<PoiType>, BlockPos>> set,
|
||||
+ Path path) {
|
||||
+ if (path != null && path.canReach()) {
|
||||
+ BlockPos target = path.getTarget();
|
||||
+ poiManager.getType(target).ifPresent(holder -> {
|
||||
+ poiManager.take(acquirablePois, (holder1, blockPos) -> blockPos.equals(target), target, 1);
|
||||
+ memoryAccessor.set(GlobalPos.of(level.dimension(), target));
|
||||
+ entityEventId.ifPresent(id -> level.broadcastEntityEvent(mob, id));
|
||||
+ map.clear();
|
||||
+ DebugPackets.sendPoiTicketCountPacket(level, target);
|
||||
+ });
|
||||
+ } else {
|
||||
+ for (Pair<Holder<PoiType>, BlockPos> pair : set) {
|
||||
+ map.computeIfAbsent(pair.getSecond().asLong(), l -> new JitteredLinearRetry(level.random, time));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Async path processing
|
||||
+
|
||||
@Nullable
|
||||
public static Path findPathToPois(Mob mob, Set<Pair<Holder<PoiType>, BlockPos>> poiPositions) {
|
||||
if (poiPositions.isEmpty()) {
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java b/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
|
||||
index 621ba76784f2b92790eca62be4d0688834335ab6..3f676309af0d5529413fa047a7f3cac99260b9ad 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/MoveToTargetSink.java
|
||||
@@ -21,6 +21,7 @@ public class MoveToTargetSink extends Behavior<Mob> {
|
||||
private int remainingCooldown;
|
||||
@Nullable
|
||||
private Path path;
|
||||
+ private boolean finishedProcessing; // DivineMC - async path processing
|
||||
@Nullable
|
||||
private BlockPos lastTargetPos;
|
||||
private float speedModifier;
|
||||
@@ -53,9 +54,11 @@ public class MoveToTargetSink extends Behavior<Mob> {
|
||||
Brain<?> brain = owner.getBrain();
|
||||
WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get();
|
||||
boolean flag = this.reachedTarget(owner, walkTarget);
|
||||
- if (!flag && this.tryComputePath(owner, walkTarget, level.getGameTime())) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.asyncPathfinding && !flag && this.tryComputePath(owner, walkTarget, level.getGameTime())) { // DivineMC - async path processing
|
||||
this.lastTargetPos = walkTarget.getTarget().currentBlockPosition();
|
||||
return true;
|
||||
+ } else if (org.bxteam.divinemc.DivineConfig.asyncPathfinding && !flag) { // DivineMC - async pathfinding
|
||||
+ return true;
|
||||
} else {
|
||||
brain.eraseMemory(MemoryModuleType.WALK_TARGET);
|
||||
if (flag) {
|
||||
@@ -69,6 +72,7 @@ public class MoveToTargetSink extends Behavior<Mob> {
|
||||
|
||||
@Override
|
||||
protected boolean canStillUse(ServerLevel level, Mob entity, long gameTime) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding && !this.finishedProcessing) return true; // DivineMC - wait for processing
|
||||
if (this.path != null && this.lastTargetPos != null) {
|
||||
Optional<WalkTarget> memory = entity.getBrain().getMemory(MemoryModuleType.WALK_TARGET);
|
||||
boolean flag = memory.map(MoveToTargetSink::isWalkTargetSpectator).orElse(false);
|
||||
@@ -95,27 +99,98 @@ public class MoveToTargetSink extends Behavior<Mob> {
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel level, Mob entity, long gameTime) {
|
||||
+ // DivineMC start - start processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ Brain<?> brain = entity.getBrain();
|
||||
+ WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get();
|
||||
+
|
||||
+ this.finishedProcessing = false;
|
||||
+ this.lastTargetPos = walkTarget.getTarget().currentBlockPosition();
|
||||
+ this.path = this.computePath(entity, walkTarget);
|
||||
+ return;
|
||||
+ }
|
||||
+ // DivineMC end - start processing
|
||||
entity.getBrain().setMemory(MemoryModuleType.PATH, this.path);
|
||||
entity.getNavigation().moveTo(this.path, (double)this.speedModifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(ServerLevel level, Mob owner, long gameTime) {
|
||||
- Path path = owner.getNavigation().getPath();
|
||||
- Brain<?> brain = owner.getBrain();
|
||||
- if (this.path != path) {
|
||||
- this.path = path;
|
||||
- brain.setMemory(MemoryModuleType.PATH, path);
|
||||
- }
|
||||
+ // DivineMC start - Async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ if (this.path != null && !this.path.isProcessed()) return; // wait for processing
|
||||
|
||||
- if (path != null && this.lastTargetPos != null) {
|
||||
- WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get();
|
||||
- if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0 && this.tryComputePath(owner, walkTarget, level.getGameTime())) {
|
||||
- this.lastTargetPos = walkTarget.getTarget().currentBlockPosition();
|
||||
- this.start(level, owner, gameTime);
|
||||
+ if (!this.finishedProcessing) {
|
||||
+ this.finishedProcessing = true;
|
||||
+
|
||||
+ Brain<?> brain = owner.getBrain();
|
||||
+ boolean canReach = this.path != null && this.path.canReach();
|
||||
+ if (canReach) {
|
||||
+ brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
|
||||
+ } else if (!brain.hasMemoryValue(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) {
|
||||
+ brain.setMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, gameTime);
|
||||
+ }
|
||||
+
|
||||
+ if (!canReach) {
|
||||
+ Optional<WalkTarget> walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET);
|
||||
+
|
||||
+ if (!walkTarget.isPresent()) return;
|
||||
+
|
||||
+ BlockPos blockPos = walkTarget.get().getTarget().currentBlockPosition();
|
||||
+ Vec3 vec3 = DefaultRandomPos.getPosTowards((PathfinderMob) owner, 10, 7, Vec3.atBottomCenterOf(blockPos), (float) Math.PI / 2F);
|
||||
+ if (vec3 != null) {
|
||||
+ // try recalculating the path using a random position
|
||||
+ this.path = owner.getNavigation().createPath(vec3.x, vec3.y, vec3.z, 0);
|
||||
+ this.finishedProcessing = false;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ owner.getBrain().setMemory(MemoryModuleType.PATH, this.path);
|
||||
+ owner.getNavigation().moveTo(this.path, this.speedModifier);
|
||||
}
|
||||
+
|
||||
+ Path path = owner.getNavigation().getPath();
|
||||
+ Brain<?> brain = owner.getBrain();
|
||||
+
|
||||
+ if (path != null && this.lastTargetPos != null && brain.hasMemoryValue(MemoryModuleType.WALK_TARGET)) {
|
||||
+ WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get(); // we know isPresent = true
|
||||
+ if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0D) {
|
||||
+ this.start(level, owner, gameTime);
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ Path path = owner.getNavigation().getPath();
|
||||
+ Brain<?> brain = owner.getBrain();
|
||||
+ if (this.path != path) {
|
||||
+ this.path = path;
|
||||
+ brain.setMemory(MemoryModuleType.PATH, path);
|
||||
+ }
|
||||
+
|
||||
+ if (path != null && this.lastTargetPos != null) {
|
||||
+ WalkTarget walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get();
|
||||
+ if (walkTarget.getTarget().currentBlockPosition().distSqr(this.lastTargetPos) > 4.0
|
||||
+ && this.tryComputePath(owner, walkTarget, level.getGameTime())) {
|
||||
+ this.lastTargetPos = walkTarget.getTarget().currentBlockPosition();
|
||||
+ this.start(level, owner, gameTime);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Async path processing
|
||||
+ }
|
||||
+
|
||||
+ // DivineMC start - Async path processing
|
||||
+ @Nullable
|
||||
+ private Path computePath(Mob entity, WalkTarget walkTarget) {
|
||||
+ BlockPos blockPos = walkTarget.getTarget().currentBlockPosition();
|
||||
+ this.speedModifier = walkTarget.getSpeedModifier();
|
||||
+ Brain<?> brain = entity.getBrain();
|
||||
+ if (this.reachedTarget(entity, walkTarget)) {
|
||||
+ brain.eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE);
|
||||
}
|
||||
+ return entity.getNavigation().createPath(blockPos, 0);
|
||||
}
|
||||
+ // DivineMC end - Async path processing
|
||||
|
||||
private boolean tryComputePath(Mob mob, WalkTarget target, long time) {
|
||||
BlockPos blockPos = target.getTarget().currentBlockPosition();
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java b/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java
|
||||
index 4f9f3367b1ca3903df03a80fa2b01a3d24e6e77d..1e9383442d0a0adf4bf621fc35108b35b1375bc7 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/SetClosestHomeAsWalkTarget.java
|
||||
@@ -60,17 +60,18 @@ public class SetClosestHomeAsWalkTarget {
|
||||
poi -> poi.is(PoiTypes.HOME), predicate, mob.blockPosition(), 48, PoiManager.Occupancy.ANY
|
||||
)
|
||||
.collect(Collectors.toSet());
|
||||
- Path path = AcquirePoi.findPathToPois(mob, set);
|
||||
- if (path != null && path.canReach()) {
|
||||
- BlockPos target = path.getTarget();
|
||||
- Optional<Holder<PoiType>> type = poiManager.getType(target);
|
||||
- if (type.isPresent()) {
|
||||
- walkTarget.set(new WalkTarget(target, speedModifier, 1));
|
||||
- DebugPackets.sendPoiTicketCountPacket(level, target);
|
||||
- }
|
||||
- } else if (mutableInt.getValue() < 5) {
|
||||
- map.long2LongEntrySet().removeIf(entry -> entry.getLongValue() < mutableLong.getValue());
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ Path possiblePath = AcquirePoi.findPathToPois(mob, set);
|
||||
+
|
||||
+ org.bxteam.divinemc.entity.pathfinding.AsyncPathProcessor.awaitProcessing(possiblePath, path -> {
|
||||
+ processPath(speedModifier, map, mutableLong, walkTarget, level, poiManager, mutableInt, path);
|
||||
+ });
|
||||
+ } else {
|
||||
+ Path path = AcquirePoi.findPathToPois(mob, set);
|
||||
+ processPath(speedModifier, map, mutableLong, walkTarget, level, poiManager, mutableInt, path);
|
||||
}
|
||||
+ // DivineMC end - async path processing
|
||||
|
||||
return true;
|
||||
} else {
|
||||
@@ -81,4 +82,26 @@ public class SetClosestHomeAsWalkTarget {
|
||||
)
|
||||
);
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - async path processing
|
||||
+ private static void processPath(float speedModifier,
|
||||
+ Long2LongMap map,
|
||||
+ MutableLong mutableLong,
|
||||
+ net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor<com.mojang.datafixers.kinds.Const.Mu<com.mojang.datafixers.util.Unit>, WalkTarget> walkTarget,
|
||||
+ net.minecraft.server.level.ServerLevel level,
|
||||
+ PoiManager poiManager,
|
||||
+ MutableInt mutableInt,
|
||||
+ @org.jetbrains.annotations.Nullable Path path) {
|
||||
+ if (path != null && path.canReach()) {
|
||||
+ BlockPos target = path.getTarget();
|
||||
+ Optional<Holder<PoiType>> type = poiManager.getType(target);
|
||||
+ if (type.isPresent()) {
|
||||
+ walkTarget.set(new WalkTarget(target, speedModifier, 1));
|
||||
+ DebugPackets.sendPoiTicketCountPacket(level, target);
|
||||
+ }
|
||||
+ } else if (mutableInt.getValue() < 5) {
|
||||
+ map.long2LongEntrySet().removeIf(entry -> entry.getLongValue() < mutableLong.getValue());
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/DoorInteractGoal.java b/net/minecraft/world/entity/ai/goal/DoorInteractGoal.java
|
||||
index d8f532c5e68ff4dff933556c4f981e9474c044e6..37f3d3888ea2a862d006cf2b201f9715bcb8ce1e 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/DoorInteractGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/DoorInteractGoal.java
|
||||
@@ -56,7 +56,7 @@ public abstract class DoorInteractGoal extends Goal {
|
||||
} else {
|
||||
GroundPathNavigation groundPathNavigation = (GroundPathNavigation)this.mob.getNavigation();
|
||||
Path path = groundPathNavigation.getPath();
|
||||
- if (path != null && !path.isDone()) {
|
||||
+ if (path != null && path.isProcessed() && !path.isDone()) { // DivineMC - async path processing
|
||||
for (int i = 0; i < Math.min(path.getNextNodeIndex() + 2, path.getNodeCount()); i++) {
|
||||
Node node = path.getNode(i);
|
||||
this.doorPos = new BlockPos(node.x, node.y + 1, node.z);
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java b/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java
|
||||
index 66a02fe7594522ef391d67e09856bf3f70fe597d..0cd0d1059ac3612ba34f1a47a5023a8d07ee612f 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/AmphibiousPathNavigation.java
|
||||
@@ -12,9 +12,25 @@ public class AmphibiousPathNavigation extends PathNavigation {
|
||||
super(mob, level);
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ private static final org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator = (org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorFeatures nodeEvaluatorFeatures) -> {
|
||||
+ AmphibiousNodeEvaluator nodeEvaluator = new AmphibiousNodeEvaluator(false);
|
||||
+ nodeEvaluator.setCanPassDoors(nodeEvaluatorFeatures.canPassDoors());
|
||||
+ nodeEvaluator.setCanFloat(nodeEvaluatorFeatures.canFloat());
|
||||
+ nodeEvaluator.setCanWalkOverFences(nodeEvaluatorFeatures.canWalkOverFences());
|
||||
+ nodeEvaluator.setCanOpenDoors(nodeEvaluatorFeatures.canOpenDoors());
|
||||
+ return nodeEvaluator;
|
||||
+ };
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.nodeEvaluator = new AmphibiousNodeEvaluator(false);
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, nodeEvaluatorGenerator);
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java b/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
index 71ea68b56b3069bdf8e47931156b6ef49ea8ce5d..0e680d3954d5847125484c2a93d9cd8e133ad8c3 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/FlyingPathNavigation.java
|
||||
@@ -16,9 +16,25 @@ public class FlyingPathNavigation extends PathNavigation {
|
||||
super(mob, level);
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ private static final org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator = (org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorFeatures nodeEvaluatorFeatures) -> {
|
||||
+ FlyNodeEvaluator nodeEvaluator = new FlyNodeEvaluator();
|
||||
+ nodeEvaluator.setCanPassDoors(nodeEvaluatorFeatures.canPassDoors());
|
||||
+ nodeEvaluator.setCanFloat(nodeEvaluatorFeatures.canFloat());
|
||||
+ nodeEvaluator.setCanWalkOverFences(nodeEvaluatorFeatures.canWalkOverFences());
|
||||
+ nodeEvaluator.setCanOpenDoors(nodeEvaluatorFeatures.canOpenDoors());
|
||||
+ return nodeEvaluator;
|
||||
+ };
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.nodeEvaluator = new FlyNodeEvaluator();
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, nodeEvaluatorGenerator);
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes);
|
||||
}
|
||||
|
||||
@@ -48,6 +64,7 @@ public class FlyingPathNavigation extends PathNavigation {
|
||||
if (this.hasDelayedRecomputation) {
|
||||
this.recomputePath();
|
||||
}
|
||||
+ if (this.path != null && !this.path.isProcessed()) return; // DivineMC - async path processing
|
||||
|
||||
if (!this.isDone()) {
|
||||
if (this.canUpdatePath()) {
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
index 045cfafb3afe8271d60852ae3c7cdcb039b44d4f..f544bf28ac6531061da08c726684687416b9426c 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java
|
||||
@@ -24,9 +24,25 @@ public class GroundPathNavigation extends PathNavigation {
|
||||
super(mob, level);
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ protected static final org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator = (org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorFeatures nodeEvaluatorFeatures) -> {
|
||||
+ WalkNodeEvaluator nodeEvaluator = new WalkNodeEvaluator();
|
||||
+ nodeEvaluator.setCanPassDoors(nodeEvaluatorFeatures.canPassDoors());
|
||||
+ nodeEvaluator.setCanFloat(nodeEvaluatorFeatures.canFloat());
|
||||
+ nodeEvaluator.setCanWalkOverFences(nodeEvaluatorFeatures.canWalkOverFences());
|
||||
+ nodeEvaluator.setCanOpenDoors(nodeEvaluatorFeatures.canOpenDoors());
|
||||
+ return nodeEvaluator;
|
||||
+ };
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.nodeEvaluator = new WalkNodeEvaluator();
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, nodeEvaluatorGenerator);
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
index 6c8fb611943aee8cabc471c63166f9b44ef14826..02814be0e1ac9b743a4c6b5b75015a5e87fc2aa6 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/PathNavigation.java
|
||||
@@ -167,6 +167,10 @@ public abstract class PathNavigation {
|
||||
return null;
|
||||
} else if (!this.canUpdatePath()) {
|
||||
return null;
|
||||
+ // DivineMC start - catch early if it's still processing these positions let it keep processing
|
||||
+ } else if (this.path instanceof org.bxteam.divinemc.entity.pathfinding.AsyncPath asyncPath && !asyncPath.isProcessed() && asyncPath.hasSameProcessingPositions(targets)) {
|
||||
+ return this.path;
|
||||
+ // DivineMC end - catch early if it's still processing these positions let it keep processing
|
||||
} else if (this.path != null && !this.path.isDone() && targets.contains(this.targetPos)) {
|
||||
return this.path;
|
||||
} else {
|
||||
@@ -191,11 +195,29 @@ public abstract class PathNavigation {
|
||||
int i = (int)(followRange + regionOffset);
|
||||
PathNavigationRegion pathNavigationRegion = new PathNavigationRegion(this.level, blockPos.offset(-i, -i, -i), blockPos.offset(i, i, i));
|
||||
Path path = this.pathFinder.findPath(pathNavigationRegion, this.mob, targets, followRange, accuracy, this.maxVisitedNodesMultiplier);
|
||||
- if (path != null && path.getTarget() != null) {
|
||||
- this.targetPos = path.getTarget();
|
||||
- this.reachRange = accuracy;
|
||||
- this.resetStuckTimeout();
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ // assign early a target position. most calls will only have 1 position
|
||||
+ if (!targets.isEmpty()) this.targetPos = targets.iterator().next();
|
||||
+
|
||||
+ org.bxteam.divinemc.entity.pathfinding.AsyncPathProcessor.awaitProcessing(path, processedPath -> {
|
||||
+ // check that processing didn't take so long that we calculated a new path
|
||||
+ if (processedPath != this.path) return;
|
||||
+
|
||||
+ if (processedPath != null && processedPath.getTarget() != null) {
|
||||
+ this.targetPos = processedPath.getTarget();
|
||||
+ this.reachRange = accuracy;
|
||||
+ this.resetStuckTimeout();
|
||||
+ }
|
||||
+ });
|
||||
+ } else {
|
||||
+ if (path != null && path.getTarget() != null) {
|
||||
+ this.targetPos = path.getTarget();
|
||||
+ this.reachRange = accuracy;
|
||||
+ this.resetStuckTimeout();
|
||||
+ }
|
||||
}
|
||||
+ // DivineMC end - async path processing
|
||||
|
||||
return path;
|
||||
}
|
||||
@@ -246,8 +268,8 @@ public abstract class PathNavigation {
|
||||
if (this.isDone()) {
|
||||
return false;
|
||||
} else {
|
||||
- this.trimPath();
|
||||
- if (this.path.getNodeCount() <= 0) {
|
||||
+ if (path.isProcessed()) this.trimPath(); // DivineMC - only trim if processed
|
||||
+ if (path.isProcessed() && this.path.getNodeCount() <= 0) { // DivineMC - only check node count if processed
|
||||
return false;
|
||||
} else {
|
||||
this.speedModifier = speed;
|
||||
@@ -270,6 +292,7 @@ public abstract class PathNavigation {
|
||||
if (this.hasDelayedRecomputation) {
|
||||
this.recomputePath();
|
||||
}
|
||||
+ if (this.path != null && !this.path.isProcessed()) return; // DivineMC - skip pathfinding if we're still processing
|
||||
|
||||
if (!this.isDone()) {
|
||||
if (this.canUpdatePath()) {
|
||||
@@ -299,6 +322,7 @@ public abstract class PathNavigation {
|
||||
}
|
||||
|
||||
protected void followThePath() {
|
||||
+ if (!this.path.isProcessed()) return; // DivineMC - skip if not processed
|
||||
Vec3 tempMobPos = this.getTempMobPos();
|
||||
this.maxDistanceToWaypoint = this.mob.getBbWidth() > 0.75F ? this.mob.getBbWidth() / 2.0F : 0.75F - this.mob.getBbWidth() / 2.0F;
|
||||
Vec3i nextNodePos = this.path.getNextNodePos();
|
||||
@@ -455,7 +479,7 @@ public abstract class PathNavigation {
|
||||
public boolean shouldRecomputePath(BlockPos pos) {
|
||||
if (this.hasDelayedRecomputation) {
|
||||
return false;
|
||||
- } else if (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0) {
|
||||
+ } else if (this.path != null && this.path.isProcessed() && !this.path.isDone() && this.path.getNodeCount() != 0) { // DivineMC - Skip if not processed
|
||||
Node endNode = this.path.getEndNode();
|
||||
Vec3 vec3 = new Vec3((endNode.x + this.mob.getX()) / 2.0, (endNode.y + this.mob.getY()) / 2.0, (endNode.z + this.mob.getZ()) / 2.0);
|
||||
return pos.closerToCenterThan(vec3, this.path.getNodeCount() - this.path.getNextNodeIndex());
|
||||
diff --git a/net/minecraft/world/entity/ai/navigation/WaterBoundPathNavigation.java b/net/minecraft/world/entity/ai/navigation/WaterBoundPathNavigation.java
|
||||
index 2979846853898d78a2df19df2287da16dbe4ae71..504911c14aad5c53aeea2c71bda3978f022601dd 100644
|
||||
--- a/net/minecraft/world/entity/ai/navigation/WaterBoundPathNavigation.java
|
||||
+++ b/net/minecraft/world/entity/ai/navigation/WaterBoundPathNavigation.java
|
||||
@@ -15,11 +15,27 @@ public class WaterBoundPathNavigation extends PathNavigation {
|
||||
super(mob, level);
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ private static final org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator = (org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorFeatures nodeEvaluatorFeatures) -> {
|
||||
+ SwimNodeEvaluator nodeEvaluator = new SwimNodeEvaluator(nodeEvaluatorFeatures.allowBreaching());
|
||||
+ nodeEvaluator.setCanPassDoors(nodeEvaluatorFeatures.canPassDoors());
|
||||
+ nodeEvaluator.setCanFloat(nodeEvaluatorFeatures.canFloat());
|
||||
+ nodeEvaluator.setCanWalkOverFences(nodeEvaluatorFeatures.canWalkOverFences());
|
||||
+ nodeEvaluator.setCanOpenDoors(nodeEvaluatorFeatures.canOpenDoors());
|
||||
+ return nodeEvaluator;
|
||||
+ };
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.allowBreaching = this.mob.getType() == EntityType.DOLPHIN;
|
||||
this.nodeEvaluator = new SwimNodeEvaluator(this.allowBreaching);
|
||||
this.nodeEvaluator.setCanPassDoors(false);
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, nodeEvaluatorGenerator);
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
|
||||
index 1f96fd5085bacb4c584576c7cb9f51e7898e9b03..9494dd144ff1115c9f0862614ef618035ee2565f 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/NearestBedSensor.java
|
||||
@@ -57,17 +57,32 @@ public class NearestBedSensor extends Sensor<Mob> {
|
||||
java.util.List<Pair<Holder<PoiType>, BlockPos>> poiposes = new java.util.ArrayList<>();
|
||||
// don't ask me why it's unbounded. ask mojang.
|
||||
io.papermc.paper.util.PoiAccess.findAnyPoiPositions(poiManager, type -> type.is(PoiTypes.HOME), predicate, entity.blockPosition(), level.purpurConfig.villagerNearestBedSensorSearchRadius, PoiManager.Occupancy.ANY, false, Integer.MAX_VALUE, poiposes); // Purpur - Configurable villager search radius
|
||||
- Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes));
|
||||
- // Paper end - optimise POI access
|
||||
- if (path != null && path.canReach()) {
|
||||
- BlockPos target = path.getTarget();
|
||||
- Optional<Holder<PoiType>> type = poiManager.getType(target);
|
||||
- if (type.isPresent()) {
|
||||
- entity.getBrain().setMemory(MemoryModuleType.NEAREST_BED, target);
|
||||
- }
|
||||
- } else if (this.triedCount < 5) {
|
||||
- this.batchCache.long2LongEntrySet().removeIf(entry -> entry.getLongValue() < this.lastUpdate);
|
||||
+ // DivineMC start - async pathfinding
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ Path possiblePath = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes));
|
||||
+ org.bxteam.divinemc.entity.pathfinding.AsyncPathProcessor.awaitProcessing(possiblePath, path -> {
|
||||
+ processPath(entity, poiManager, path);
|
||||
+ });
|
||||
+ } else {
|
||||
+ Path path = AcquirePoi.findPathToPois(entity, new java.util.HashSet<>(poiposes));
|
||||
+ // Paper end - optimise POI access
|
||||
+ processPath(entity, poiManager, path);
|
||||
+ }
|
||||
+ // DivineMC end - async pathfinding
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // DivineMC start - async pathfinding
|
||||
+ private void processPath(Mob entity, PoiManager poiManager, @org.jetbrains.annotations.Nullable Path path) {
|
||||
+ if (path != null && path.canReach()) {
|
||||
+ BlockPos target = path.getTarget();
|
||||
+ Optional<Holder<PoiType>> type = poiManager.getType(target);
|
||||
+ if (type.isPresent()) {
|
||||
+ entity.getBrain().setMemory(MemoryModuleType.NEAREST_BED, target);
|
||||
}
|
||||
+ } else if (this.triedCount < 5) {
|
||||
+ this.batchCache.long2LongEntrySet().removeIf(entry -> entry.getLongValue() < this.lastUpdate);
|
||||
}
|
||||
}
|
||||
+ // DivineMC end - async pathfinding
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java
|
||||
index d5727999eb67ff30dbf47865d59452483338e170..ddbee0f0f42fae0a26321bb324d22f5e7520ae72 100644
|
||||
--- a/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -936,7 +936,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
} else {
|
||||
Bee.this.pathfindRandomlyTowards(Bee.this.hivePos);
|
||||
}
|
||||
- } else {
|
||||
+ } else if (navigation.getPath() != null && navigation.getPath().isProcessed()) { // DivineMC - check processing
|
||||
boolean flag = this.pathfindDirectlyTowards(Bee.this.hivePos);
|
||||
if (!flag) {
|
||||
this.dropAndBlacklistHive();
|
||||
@@ -990,7 +990,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
return true;
|
||||
} else {
|
||||
Path path = Bee.this.navigation.getPath();
|
||||
- return path != null && path.getTarget().equals(pos) && path.canReach() && path.isDone();
|
||||
+ return path != null && path.isProcessed() && path.getTarget().equals(pos) && path.canReach() && path.isDone(); // DivineMC - ensure path is processed
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/animal/frog/Frog.java b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
index 4aabb98e0b37b652ad4d334b99c48a818c2859b4..dfcba5c2c8a489ebe74c2d5c1fa980c401806757 100644
|
||||
--- a/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
@@ -473,6 +473,17 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
||||
super(mob, level);
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ private static final org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator = (org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorFeatures nodeEvaluatorFeatures) -> {
|
||||
+ Frog.FrogNodeEvaluator nodeEvaluator = new Frog.FrogNodeEvaluator(true);
|
||||
+ nodeEvaluator.setCanPassDoors(nodeEvaluatorFeatures.canPassDoors());
|
||||
+ nodeEvaluator.setCanFloat(nodeEvaluatorFeatures.canFloat());
|
||||
+ nodeEvaluator.setCanWalkOverFences(nodeEvaluatorFeatures.canWalkOverFences());
|
||||
+ nodeEvaluator.setCanOpenDoors(nodeEvaluatorFeatures.canOpenDoors());
|
||||
+ return nodeEvaluator;
|
||||
+ };
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
@Override
|
||||
public boolean canCutCorner(PathType pathType) {
|
||||
return pathType != PathType.WATER_BORDER && super.canCutCorner(pathType);
|
||||
@@ -481,6 +492,11 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.nodeEvaluator = new Frog.FrogNodeEvaluator(true);
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, nodeEvaluatorGenerator);
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes);
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/monster/Drowned.java b/net/minecraft/world/entity/monster/Drowned.java
|
||||
index 6c73245b8d04f194e72165aa0000ca79a95db59d..2686df57d9d48db1438278d0d053bdbd3c65c0a7 100644
|
||||
--- a/net/minecraft/world/entity/monster/Drowned.java
|
||||
+++ b/net/minecraft/world/entity/monster/Drowned.java
|
||||
@@ -313,7 +313,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
||||
|
||||
protected boolean closeToNextPos() {
|
||||
Path path = this.getNavigation().getPath();
|
||||
- if (path != null) {
|
||||
+ if (path != null && path.isProcessed()) { // DivineMC - ensure path is processed
|
||||
BlockPos target = path.getTarget();
|
||||
if (target != null) {
|
||||
double d = this.distanceToSqr(target.getX(), target.getY(), target.getZ());
|
||||
diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java
|
||||
index 241526239bdbd5d9276f85e7fca46a7051f46a25..2329973f735e1ae7fbb76798dc113f4261c906b7 100644
|
||||
--- a/net/minecraft/world/entity/monster/Strider.java
|
||||
+++ b/net/minecraft/world/entity/monster/Strider.java
|
||||
@@ -579,9 +579,25 @@ public class Strider extends Animal implements ItemSteerable, Saddleable {
|
||||
super(strider, level);
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ private static final org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator = (org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorFeatures nodeEvaluatorFeatures) -> {
|
||||
+ WalkNodeEvaluator nodeEvaluator = new WalkNodeEvaluator();
|
||||
+ nodeEvaluator.setCanPassDoors(nodeEvaluatorFeatures.canPassDoors());
|
||||
+ nodeEvaluator.setCanFloat(nodeEvaluatorFeatures.canFloat());
|
||||
+ nodeEvaluator.setCanWalkOverFences(nodeEvaluatorFeatures.canWalkOverFences());
|
||||
+ nodeEvaluator.setCanOpenDoors(nodeEvaluatorFeatures.canOpenDoors());
|
||||
+ return nodeEvaluator;
|
||||
+ };
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.nodeEvaluator = new WalkNodeEvaluator();
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, nodeEvaluatorGenerator);
|
||||
+ }
|
||||
+ // DivineMC end
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes);
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/warden/Warden.java b/net/minecraft/world/entity/monster/warden/Warden.java
|
||||
index e4b8a74fae6d058a9a75a12d2ff08c7984442538..59a12809e5c7f5ee85ca1f587f6b77383a1ff062 100644
|
||||
--- a/net/minecraft/world/entity/monster/warden/Warden.java
|
||||
+++ b/net/minecraft/world/entity/monster/warden/Warden.java
|
||||
@@ -597,6 +597,16 @@ public class Warden extends Monster implements VibrationSystem {
|
||||
@Override
|
||||
protected PathFinder createPathFinder(int maxVisitedNodes) {
|
||||
this.nodeEvaluator = new WalkNodeEvaluator();
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncPathfinding) {
|
||||
+ return new PathFinder(this.nodeEvaluator, maxVisitedNodes, GroundPathNavigation.nodeEvaluatorGenerator) {
|
||||
+ @Override
|
||||
+ protected float distance(Node first, Node second) {
|
||||
+ return first.distanceToXZ(second);
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
return new PathFinder(this.nodeEvaluator, maxVisitedNodes) {
|
||||
@Override
|
||||
protected float distance(Node first, Node second) {
|
||||
diff --git a/net/minecraft/world/level/pathfinder/Path.java b/net/minecraft/world/level/pathfinder/Path.java
|
||||
index d6d3c8f5e5dd4a8cab0d3fcc131c3a59f06130c6..839653a997f1e10970fa2956fadaf493808cb206 100644
|
||||
--- a/net/minecraft/world/level/pathfinder/Path.java
|
||||
+++ b/net/minecraft/world/level/pathfinder/Path.java
|
||||
@@ -26,6 +26,17 @@ public class Path {
|
||||
this.reached = reached;
|
||||
}
|
||||
|
||||
+ // DivineMC start - async path processing
|
||||
+ /**
|
||||
+ * checks if the path is completely processed in the case of it being computed async
|
||||
+ *
|
||||
+ * @return true if the path is processed
|
||||
+ */
|
||||
+ public boolean isProcessed() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ // DivineMC end - async path processing
|
||||
+
|
||||
public void advance() {
|
||||
this.nextNodeIndex++;
|
||||
}
|
||||
@@ -99,6 +110,7 @@ public class Path {
|
||||
}
|
||||
|
||||
public boolean sameAs(@Nullable Path pathentity) {
|
||||
+ if (pathentity == this) return true; // DivineMC - async path processing
|
||||
if (pathentity == null) {
|
||||
return false;
|
||||
} else if (pathentity.nodes.size() != this.nodes.size()) {
|
||||
diff --git a/net/minecraft/world/level/pathfinder/PathFinder.java b/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
index c2baadcdceb1df6a881d6f73aa4eb4dd264bcdfe..965c1d2dd1acd542936fad8034c2de1746193355 100644
|
||||
--- a/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
+++ b/net/minecraft/world/level/pathfinder/PathFinder.java
|
||||
@@ -22,11 +22,19 @@ public class PathFinder {
|
||||
public final NodeEvaluator nodeEvaluator;
|
||||
private static final boolean DEBUG = false;
|
||||
private final BinaryHeap openSet = new BinaryHeap();
|
||||
+ private final @Nullable org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator; // DivineMC - we use this later to generate an evaluator
|
||||
|
||||
- public PathFinder(NodeEvaluator nodeEvaluator, int maxVisitedNodes) {
|
||||
+ // DivineMC start - support nodeEvaluatorgenerators
|
||||
+ public PathFinder(NodeEvaluator nodeEvaluator, int maxVisitedNodes, @Nullable org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorGenerator nodeEvaluatorGenerator) { // DivineMC - add nodeEvaluatorGenerator
|
||||
this.nodeEvaluator = nodeEvaluator;
|
||||
this.maxVisitedNodes = maxVisitedNodes;
|
||||
+ this.nodeEvaluatorGenerator = nodeEvaluatorGenerator;
|
||||
+ }
|
||||
+
|
||||
+ public PathFinder(NodeEvaluator nodeEvaluator, int maxVisitedNodes) {
|
||||
+ this(nodeEvaluator, maxVisitedNodes, null);
|
||||
}
|
||||
+ // DivineMC end - support nodeEvaluatorgenerators
|
||||
|
||||
public void setMaxVisitedNodes(int maxVisitedNodes) {
|
||||
this.maxVisitedNodes = maxVisitedNodes;
|
||||
@@ -34,26 +42,63 @@ public class PathFinder {
|
||||
|
||||
@Nullable
|
||||
public Path findPath(PathNavigationRegion region, Mob mob, Set<BlockPos> targetPositions, float maxRange, int accuracy, float searchDepthMultiplier) {
|
||||
- this.openSet.clear();
|
||||
- this.nodeEvaluator.prepare(region, mob);
|
||||
- Node start = this.nodeEvaluator.getStart();
|
||||
+ // DivineMC start - use a generated evaluator if we have one otherwise run sync
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.asyncPathfinding)
|
||||
+ this.openSet.clear(); // it's always cleared in processPath
|
||||
+ NodeEvaluator nodeEvaluator = this.nodeEvaluatorGenerator == null
|
||||
+ ? this.nodeEvaluator
|
||||
+ : org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorCache.takeNodeEvaluator(this.nodeEvaluatorGenerator, this.nodeEvaluator);
|
||||
+ nodeEvaluator.prepare(region, mob);
|
||||
+ Node start = nodeEvaluator.getStart();
|
||||
+ // DivineMC end - use a generated evaluator if we have one otherwise run sync
|
||||
if (start == null) {
|
||||
+ org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorCache.removeNodeEvaluator(nodeEvaluator); // DivineMC - handle nodeEvaluatorGenerator
|
||||
return null;
|
||||
} else {
|
||||
// Paper start - Perf: remove streams and optimize collection
|
||||
List<Map.Entry<Target, BlockPos>> map = Lists.newArrayList();
|
||||
for (BlockPos pos : targetPositions) {
|
||||
- map.add(new java.util.AbstractMap.SimpleEntry<>(this.nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), pos));
|
||||
+ map.add(new java.util.AbstractMap.SimpleEntry<>(nodeEvaluator.getTarget(pos.getX(), pos.getY(), pos.getZ()), pos)); // DivineMC - handle nodeEvaluatorGenerator
|
||||
}
|
||||
// Paper end - Perf: remove streams and optimize collection
|
||||
- Path path = this.findPath(start, map, maxRange, accuracy, searchDepthMultiplier);
|
||||
- this.nodeEvaluator.done();
|
||||
- return path;
|
||||
+ // DivineMC start - async path processing
|
||||
+ if (this.nodeEvaluatorGenerator == null) {
|
||||
+ // run sync :(
|
||||
+ org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorCache.removeNodeEvaluator(nodeEvaluator);
|
||||
+ return this.findPath(start, map, maxRange, accuracy, searchDepthMultiplier);
|
||||
+ }
|
||||
+
|
||||
+ return new org.bxteam.divinemc.entity.pathfinding.AsyncPath(Lists.newArrayList(), targetPositions, () -> {
|
||||
+ try {
|
||||
+ return this.processPath(nodeEvaluator, start, map, maxRange, accuracy, searchDepthMultiplier);
|
||||
+ } catch (Exception e) {
|
||||
+ e.printStackTrace();
|
||||
+ return null;
|
||||
+ } finally {
|
||||
+ nodeEvaluator.done();
|
||||
+ org.bxteam.divinemc.entity.pathfinding.NodeEvaluatorCache.returnNodeEvaluator(nodeEvaluator);
|
||||
+ }
|
||||
+ });
|
||||
+ // DivineMC end - async path processing
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Path findPath(Node node, List<Map.Entry<Target, BlockPos>> positions, float maxRange, int accuracy, float searchDepthMultiplier) { // Paper - optimize collection
|
||||
+ // DivineMC start - split pathfinding into the original sync method for compat and processing for delaying
|
||||
+ try {
|
||||
+ return this.processPath(this.nodeEvaluator, node, positions, maxRange, accuracy, searchDepthMultiplier);
|
||||
+ } catch (Exception e) {
|
||||
+ e.printStackTrace();
|
||||
+ return null;
|
||||
+ } finally {
|
||||
+ this.nodeEvaluator.done();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private synchronized @org.jetbrains.annotations.NotNull Path processPath(NodeEvaluator nodeEvaluator, Node node, List<Map.Entry<Target, BlockPos>> positions, float maxRange, int accuracy, float searchDepthMultiplier) { // sync to only use the caching functions in this class on a single thread
|
||||
+ org.apache.commons.lang3.Validate.isTrue(!positions.isEmpty()); // ensure that we have at least one position, which means we'll always return a path
|
||||
+ // DivineMC end - split pathfinding into the original sync method for compat and processing for delaying
|
||||
// Set<Target> set = targetPositions.keySet(); // Paper
|
||||
node.g = 0.0F;
|
||||
node.h = this.getBestH(node, positions); // Paper - optimize collection
|
||||
@@ -89,7 +134,7 @@ public class PathFinder {
|
||||
}
|
||||
|
||||
if (!(node1.distanceTo(node) >= maxRange)) {
|
||||
- int neighbors = this.nodeEvaluator.getNeighbors(this.neighbors, node1);
|
||||
+ int neighbors = nodeEvaluator.getNeighbors(this.neighbors, node1); // DivineMC - use provided nodeEvaluator
|
||||
|
||||
for (int i2 = 0; i2 < neighbors; i2++) {
|
||||
Node node2 = this.neighbors[i2];
|
||||
@@ -1,294 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Tue, 28 Jan 2025 01:18:49 +0300
|
||||
Subject: [PATCH] Multithreaded Tracker
|
||||
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||
index dd2509996bfd08e8c3f9f2be042229eac6d7692d..8ef5a1aaac9c27873ce746eb281f77bb318a3c69 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||
@@ -342,7 +342,11 @@ public final class RegionizedPlayerChunkLoader {
|
||||
private boolean canGenerateChunks = true;
|
||||
|
||||
private final ArrayDeque<ChunkHolderManager.TicketOperation<?, ?>> delayedTicketOps = new ArrayDeque<>();
|
||||
- private final LongOpenHashSet sentChunks = new LongOpenHashSet();
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ private final LongOpenHashSet sentChunks = org.bxteam.divinemc.DivineConfig.multithreadedEnabled && !org.bxteam.divinemc.DivineConfig.multithreadedCompatModeEnabled
|
||||
+ ? new org.bxteam.divinemc.util.map.ConcurrentLongHashSet()
|
||||
+ : new LongOpenHashSet();
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
|
||||
private static final byte CHUNK_TICKET_STAGE_NONE = 0;
|
||||
private static final byte CHUNK_TICKET_STAGE_LOADING = 1;
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index d3d9926d504fa6b3384be5ae06b2843ebb7f807c..965899a98223b15bd770378c202873cbf15b714d 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -951,6 +951,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
// Paper end - optimise entity tracker
|
||||
|
||||
protected void tick() {
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ if (org.bxteam.divinemc.DivineConfig.multithreadedEnabled) {
|
||||
+ final ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel level = this.level;
|
||||
+ org.bxteam.divinemc.entity.tracking.MultithreadedTracker.tick(level);
|
||||
+ return;
|
||||
+ }
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
// Paper start - optimise entity tracker
|
||||
if (true) {
|
||||
this.newTrackerTick();
|
||||
@@ -1073,7 +1080,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
- public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ public final Set<ServerPlayerConnection> seenBy = org.bxteam.divinemc.DivineConfig.multithreadedEnabled
|
||||
+ ? com.google.common.collect.Sets.newConcurrentHashSet()
|
||||
+ : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
|
||||
// Paper start - optimise entity tracker
|
||||
private long lastChunkUpdate = -1L;
|
||||
@@ -1100,21 +1111,55 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
this.lastTrackedChunk = chunk;
|
||||
|
||||
final ServerPlayer[] playersRaw = players.getRawDataUnchecked();
|
||||
+ final int playersLen = players.size(); // Ensure length won't change in the future tasks
|
||||
+
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ if (org.bxteam.divinemc.DivineConfig.multithreadedEnabled && org.bxteam.divinemc.DivineConfig.multithreadedCompatModeEnabled) {
|
||||
+ final boolean isServerPlayer = this.entity instanceof ServerPlayer;
|
||||
+ final boolean isRealPlayer = isServerPlayer && ((ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer) this.entity).moonrise$isRealPlayer();
|
||||
+ Runnable updatePlayerTasks = () -> {
|
||||
+ for (int i = 0; i < playersLen; ++i) {
|
||||
+ final ServerPlayer player = playersRaw[i];
|
||||
+ this.updatePlayer(player);
|
||||
+ }
|
||||
|
||||
- for (int i = 0, len = players.size(); i < len; ++i) {
|
||||
- final ServerPlayer player = playersRaw[i];
|
||||
- this.updatePlayer(player);
|
||||
- }
|
||||
+ if (lastChunkUpdate != currChunkUpdate || lastTrackedChunk != chunk) {
|
||||
+ // need to purge any players possible not in the chunk list
|
||||
+ for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) {
|
||||
+ final ServerPlayer player = conn.getPlayer();
|
||||
+ if (!players.contains(player)) {
|
||||
+ this.removePlayer(player);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ // Only update asynchronously for real player, and sync update for fake players
|
||||
+ // This can fix compatibility issue with NPC plugins using real entity type, like Citizens
|
||||
+ // To prevent visible issue with player type NPCs
|
||||
+ // btw, still recommend to use packet based NPC plugins, like ZNPC Plus, Adyeshach, Fancy NPC, etc.
|
||||
+ if (isRealPlayer || !isServerPlayer) {
|
||||
+ org.bxteam.divinemc.entity.tracking.MultithreadedTracker.getTrackerExecutor().execute(updatePlayerTasks);
|
||||
+ } else {
|
||||
+ updatePlayerTasks.run();
|
||||
+ }
|
||||
+ } else {
|
||||
+ for (int i = 0, len = players.size(); i < len; ++i) {
|
||||
+ final ServerPlayer player = playersRaw[i];
|
||||
+ this.updatePlayer(player);
|
||||
+ }
|
||||
|
||||
- if (lastChunkUpdate != currChunkUpdate || lastTrackedChunk != chunk) {
|
||||
- // need to purge any players possible not in the chunk list
|
||||
- for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) {
|
||||
- final ServerPlayer player = conn.getPlayer();
|
||||
- if (!players.contains(player)) {
|
||||
- this.removePlayer(player);
|
||||
+ if (lastChunkUpdate != currChunkUpdate || lastTrackedChunk != chunk) {
|
||||
+ // need to purge any players possible not in the chunk list
|
||||
+ for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) {
|
||||
+ final ServerPlayer player = conn.getPlayer();
|
||||
+ if (!players.contains(player)) {
|
||||
+ this.removePlayer(player);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1176,7 +1221,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public void broadcast(Packet<?> packet) {
|
||||
- for (ServerPlayerConnection serverPlayerConnection : this.seenBy) {
|
||||
+ for (ServerPlayerConnection serverPlayerConnection : this.seenBy.toArray(new ServerPlayerConnection[0])) { // DivineMC - Multithreaded tracker
|
||||
serverPlayerConnection.send(packet);
|
||||
}
|
||||
}
|
||||
@@ -1189,21 +1234,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
|
||||
public void broadcastRemoved() {
|
||||
- for (ServerPlayerConnection serverPlayerConnection : this.seenBy) {
|
||||
+ for (ServerPlayerConnection serverPlayerConnection : this.seenBy.toArray(new ServerPlayerConnection[0])) { // DivineMC - Multithreaded tracker
|
||||
this.serverEntity.removePairing(serverPlayerConnection.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(ServerPlayer player) {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot
|
||||
if (this.seenBy.remove(player.connection)) {
|
||||
this.serverEntity.removePairing(player);
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePlayer(ServerPlayer player) {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
|
||||
if (player != this.entity) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.multithreadedEnabled && player == null) return; // DivineMC - Multithreaded tracker
|
||||
// Paper start - remove allocation of Vec3D here
|
||||
// Vec3 vec3 = player.position().subtract(this.entity.position());
|
||||
double vec3_dx = player.getX() - this.entity.getX();
|
||||
diff --git a/net/minecraft/server/level/ServerBossEvent.java b/net/minecraft/server/level/ServerBossEvent.java
|
||||
index f106373ef3ac4a8685c2939c9e8361688a285913..3b4dff8867e91884b5720ca8a9cb64af655f8475 100644
|
||||
--- a/net/minecraft/server/level/ServerBossEvent.java
|
||||
+++ b/net/minecraft/server/level/ServerBossEvent.java
|
||||
@@ -13,7 +13,11 @@ import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.BossEvent;
|
||||
|
||||
public class ServerBossEvent extends BossEvent {
|
||||
- private final Set<ServerPlayer> players = Sets.newHashSet();
|
||||
+ // DivineMC start - Multithreaded tracker - players can be removed in async tracking
|
||||
+ private final Set<ServerPlayer> players = org.bxteam.divinemc.DivineConfig.multithreadedEnabled
|
||||
+ ? Sets.newConcurrentHashSet()
|
||||
+ : Sets.newHashSet();
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
private final Set<ServerPlayer> unmodifiablePlayers = Collections.unmodifiableSet(this.players);
|
||||
public boolean visible = true;
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||
index 0fb253aa55a24b56b17f524b3261c5b75c7d7e59..b6053158f5d9b6ad325ea075ab7c60f9966ba496 100644
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -110,8 +110,16 @@ public class ServerEntity {
|
||||
.forEach(
|
||||
removedPassenger -> {
|
||||
if (removedPassenger instanceof ServerPlayer serverPlayer1) {
|
||||
- serverPlayer1.connection
|
||||
- .teleport(serverPlayer1.getX(), serverPlayer1.getY(), serverPlayer1.getZ(), serverPlayer1.getYRot(), serverPlayer1.getXRot());
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ if (org.bxteam.divinemc.DivineConfig.multithreadedEnabled && Thread.currentThread() instanceof org.bxteam.divinemc.entity.tracking.MultithreadedTracker.MultithreadedTrackerThread) {
|
||||
+ net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> serverPlayer1.connection
|
||||
+ .teleport(serverPlayer1.getX(), serverPlayer1.getY(), serverPlayer1.getZ(), serverPlayer1.getYRot(), serverPlayer1.getXRot())
|
||||
+ );
|
||||
+ } else {
|
||||
+ serverPlayer1.connection
|
||||
+ .teleport(serverPlayer1.getX(), serverPlayer1.getY(), serverPlayer1.getZ(), serverPlayer1.getYRot(), serverPlayer1.getXRot());
|
||||
+ }
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -410,12 +418,13 @@ public class ServerEntity {
|
||||
if (this.entity instanceof LivingEntity) {
|
||||
Set<AttributeInstance> attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
|
||||
if (!attributesToSync.isEmpty()) {
|
||||
+ final Set<AttributeInstance> copy = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(attributesToSync); // DivineMC - Multithreaded tracker
|
||||
// CraftBukkit start - Send scaled max health
|
||||
if (this.entity instanceof ServerPlayer serverPlayer) {
|
||||
- serverPlayer.getBukkitEntity().injectScaledMaxHealth(attributesToSync, false);
|
||||
+ serverPlayer.getBukkitEntity().injectScaledMaxHealth(copy, false); // DivineMC - Multithreaded tracker
|
||||
}
|
||||
// CraftBukkit end
|
||||
- this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), attributesToSync));
|
||||
+ this.broadcastAndSend(new ClientboundUpdateAttributesPacket(this.entity.getId(), copy)); // DivineMC - Multithreaded tracker
|
||||
}
|
||||
|
||||
attributesToSync.clear();
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index c229d69ce3d007e4cb57e559611b3fca7a03562f..ba5ca5213fafd60b2257409f334a7c6b28fe918a 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2497,7 +2497,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
|
||||
@Override
|
||||
public LevelEntityGetter<Entity> getEntities() {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
|
||||
+ //org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // DivineMC - Multithreaded tracker
|
||||
return this.moonrise$getEntityLookup(); // Paper - rewrite chunk system
|
||||
}
|
||||
|
||||
@@ -2724,7 +2724,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
|
||||
map.carriedByPlayers.remove(player);
|
||||
- if (map.carriedBy.removeIf(holdingPlayer -> holdingPlayer.player == player)) {
|
||||
+ if (map.carriedBy.removeIf(holdingPlayer -> holdingPlayer != null && holdingPlayer.player == player)) { // DivineMC - Multithreaded tracker
|
||||
map.decorations.remove(player.getName().getString());
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 56a22d19a82a937c08cb4527b0f67f219a6bb8a0..f8c76bb2c9fa625e191036dc58ef3dfb1d4ee930 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1822,7 +1822,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
public void internalTeleport(PositionMoveRotation posMoveRotation, Set<Relative> relatives) {
|
||||
- org.spigotmc.AsyncCatcher.catchOp("teleport"); // Paper
|
||||
+ //org.spigotmc.AsyncCatcher.catchOp("teleport"); // DivineMC - Multithreaded tracker
|
||||
// Paper start - Prevent teleporting dead entities
|
||||
if (this.player.isRemoved()) {
|
||||
LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
|
||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||
index 8013594bb4844e7a8abf28123958e7f632d39341..72593629324ccd4d70b8ed86a90fb69785d57f5f 100644
|
||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeInstance.java
|
||||
@@ -24,8 +24,11 @@ public class AttributeInstance {
|
||||
private final Map<AttributeModifier.Operation, Map<ResourceLocation, AttributeModifier>> modifiersByOperation = Maps.newEnumMap(
|
||||
AttributeModifier.Operation.class
|
||||
);
|
||||
- private final Map<ResourceLocation, AttributeModifier> modifierById = new Object2ObjectArrayMap<>();
|
||||
- private final Map<ResourceLocation, AttributeModifier> permanentModifiers = new Object2ObjectArrayMap<>();
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ private final boolean multiThreadedTrackingEnabled = org.bxteam.divinemc.DivineConfig.multithreadedEnabled;
|
||||
+ private final Map<ResourceLocation, AttributeModifier> modifierById = multiThreadedTrackingEnabled ? new java.util.concurrent.ConcurrentHashMap<>() : new Object2ObjectArrayMap<>();
|
||||
+ private final Map<ResourceLocation, AttributeModifier> permanentModifiers = multiThreadedTrackingEnabled ? new java.util.concurrent.ConcurrentHashMap<>() : new Object2ObjectArrayMap<>();
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
private double baseValue;
|
||||
private boolean dirty = true;
|
||||
private double cachedValue;
|
||||
diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
index a25d74592e89e3d6339479c6dc2b6f45d1932cfc..621b183211b8148bb8db256d2119c82f8a2c626b 100644
|
||||
--- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
+++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
||||
@@ -19,9 +19,12 @@ import org.slf4j.Logger;
|
||||
|
||||
public class AttributeMap {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- private final Map<Holder<Attribute>, AttributeInstance> attributes = new Object2ObjectOpenHashMap<>();
|
||||
- private final Set<AttributeInstance> attributesToSync = new ObjectOpenHashSet<>();
|
||||
- private final Set<AttributeInstance> attributesToUpdate = new ObjectOpenHashSet<>();
|
||||
+ // DivineMC start - Multithreaded tracker
|
||||
+ private final boolean multiThreadedTrackingEnabled = org.bxteam.divinemc.DivineConfig.multithreadedEnabled;
|
||||
+ private final Map<Holder<Attribute>, AttributeInstance> attributes = multiThreadedTrackingEnabled ? new java.util.concurrent.ConcurrentHashMap<>() : new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0);
|
||||
+ private final Set<AttributeInstance> attributesToSync = multiThreadedTrackingEnabled ? com.google.common.collect.Sets.newConcurrentHashSet() : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||
+ private final Set<AttributeInstance> attributesToUpdate = multiThreadedTrackingEnabled ? com.google.common.collect.Sets.newConcurrentHashSet() : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0);
|
||||
+ // DivineMC end - Multithreaded tracker
|
||||
private final AttributeSupplier supplier;
|
||||
private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables
|
||||
|
||||
diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
index 681dec447486138088fe5f705ef4fadab531139f..3d6aad86519be3e1449d3288369a41aebb924c90 100644
|
||||
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
@@ -279,6 +279,7 @@ public class MapItemSavedData extends SavedData {
|
||||
|
||||
for (int i = 0; i < this.carriedBy.size(); i++) {
|
||||
MapItemSavedData.HoldingPlayer holdingPlayer1 = this.carriedBy.get(i);
|
||||
+ if (holdingPlayer1 == null) continue; // DivineMC - Multithreaded tracker
|
||||
Player player1 = holdingPlayer1.player;
|
||||
String string = player1.getName().getString();
|
||||
if (!player1.isRemoved() && (player1.getInventory().contains(predicate) || mapStack.isFramed())) {
|
||||
@@ -1,129 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Wed, 29 Jan 2025 00:54:19 +0300
|
||||
Subject: [PATCH] Async locate command
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/commands/LocateCommand.java b/net/minecraft/server/commands/LocateCommand.java
|
||||
index 13bcd8653d766cd0b754a22e9aab261fbc62b0a5..0bc2d17e9bad62f62ab171feb2a92b87e1c3ba6a 100644
|
||||
--- a/net/minecraft/server/commands/LocateCommand.java
|
||||
+++ b/net/minecraft/server/commands/LocateCommand.java
|
||||
@@ -103,44 +103,77 @@ public class LocateCommand {
|
||||
}
|
||||
|
||||
private static int locateStructure(CommandSourceStack source, ResourceOrTagKeyArgument.Result<Structure> structure) throws CommandSyntaxException {
|
||||
- Registry<Structure> registry = source.getLevel().registryAccess().lookupOrThrow(Registries.STRUCTURE);
|
||||
- HolderSet<Structure> holderSet = (HolderSet<Structure>)getHolders(structure, registry)
|
||||
- .orElseThrow(() -> ERROR_STRUCTURE_INVALID.create(structure.asPrintable()));
|
||||
- BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
- ServerLevel level = source.getLevel();
|
||||
- Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
- Pair<BlockPos, Holder<Structure>> pair = level.getChunkSource().getGenerator().findNearestMapStructure(level, holderSet, blockPos, 100, false);
|
||||
- stopwatch.stop();
|
||||
- if (pair == null) {
|
||||
- throw ERROR_STRUCTURE_NOT_FOUND.create(structure.asPrintable());
|
||||
- } else {
|
||||
- return showLocateResult(source, structure, blockPos, pair, "commands.locate.structure.success", false, stopwatch.elapsed());
|
||||
- }
|
||||
+ // DivineMC start - Async structure locate
|
||||
+ io.papermc.paper.util.MCUtil.scheduleAsyncTask(() -> {
|
||||
+ Registry<Structure> registry = source.getLevel().registryAccess().lookupOrThrow(Registries.STRUCTURE);
|
||||
+ HolderSet<Structure> holderSet;
|
||||
+ try {
|
||||
+ holderSet = getHolders(structure, registry)
|
||||
+ .orElseThrow(() -> ERROR_STRUCTURE_INVALID.create(structure.asPrintable()));
|
||||
+ } catch (CommandSyntaxException e) {
|
||||
+ source.sendFailure(Component.literal(e.getMessage()));
|
||||
+ return;
|
||||
+ }
|
||||
+ BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
+ ServerLevel level = source.getLevel();
|
||||
+ Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
+ Pair<BlockPos, Holder<Structure>> pair = level.getChunkSource().getGenerator().findNearestMapStructure(level, holderSet, blockPos, 100, false);
|
||||
+ stopwatch.stop();
|
||||
+ if (pair == null) {
|
||||
+ try {
|
||||
+ throw ERROR_STRUCTURE_NOT_FOUND.create(structure.asPrintable());
|
||||
+ } catch (CommandSyntaxException e) {
|
||||
+ source.sendFailure(Component.literal(e.getMessage()));
|
||||
+ }
|
||||
+ } else {
|
||||
+ showLocateResult(source, structure, blockPos, pair, "commands.locate.structure.success", false, stopwatch.elapsed());
|
||||
+ }
|
||||
+ });
|
||||
+ return 0;
|
||||
+ // DivineMC end - Async structure locate
|
||||
}
|
||||
|
||||
private static int locateBiome(CommandSourceStack source, ResourceOrTagArgument.Result<Biome> biome) throws CommandSyntaxException {
|
||||
- BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
- Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
- Pair<BlockPos, Holder<Biome>> pair = source.getLevel().findClosestBiome3d(biome, blockPos, 6400, 32, 64);
|
||||
- stopwatch.stop();
|
||||
- if (pair == null) {
|
||||
- throw ERROR_BIOME_NOT_FOUND.create(biome.asPrintable());
|
||||
- } else {
|
||||
- return showLocateResult(source, biome, blockPos, pair, "commands.locate.biome.success", true, stopwatch.elapsed());
|
||||
- }
|
||||
+ // DivineMC start - Async biome locate
|
||||
+ io.papermc.paper.util.MCUtil.scheduleAsyncTask(() -> {
|
||||
+ BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
+ Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
+ Pair<BlockPos, Holder<Biome>> pair = source.getLevel().findClosestBiome3d(biome, blockPos, 6400, 32, 64);
|
||||
+ stopwatch.stop();
|
||||
+ if (pair == null) {
|
||||
+ try {
|
||||
+ throw ERROR_BIOME_NOT_FOUND.create(biome.asPrintable());
|
||||
+ } catch (CommandSyntaxException e) {
|
||||
+ source.sendFailure(Component.literal(e.getMessage()));
|
||||
+ }
|
||||
+ } else {
|
||||
+ showLocateResult(source, biome, blockPos, pair, "commands.locate.biome.success", true, stopwatch.elapsed());
|
||||
+ }
|
||||
+ });
|
||||
+ return 0;
|
||||
+ // DivineMC end - Async biome locate
|
||||
}
|
||||
|
||||
private static int locatePoi(CommandSourceStack source, ResourceOrTagArgument.Result<PoiType> poiType) throws CommandSyntaxException {
|
||||
- BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
- ServerLevel level = source.getLevel();
|
||||
- Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
- Optional<Pair<Holder<PoiType>, BlockPos>> optional = level.getPoiManager().findClosestWithType(poiType, blockPos, 256, PoiManager.Occupancy.ANY);
|
||||
- stopwatch.stop();
|
||||
- if (optional.isEmpty()) {
|
||||
- throw ERROR_POI_NOT_FOUND.create(poiType.asPrintable());
|
||||
- } else {
|
||||
- return showLocateResult(source, poiType, blockPos, optional.get().swap(), "commands.locate.poi.success", false, stopwatch.elapsed());
|
||||
- }
|
||||
+ // DivineMC start - Async poi locate
|
||||
+ io.papermc.paper.util.MCUtil.scheduleAsyncTask(() -> {
|
||||
+ BlockPos blockPos = BlockPos.containing(source.getPosition());
|
||||
+ ServerLevel level = source.getLevel();
|
||||
+ Stopwatch stopwatch = Stopwatch.createStarted(Util.TICKER);
|
||||
+ Optional<Pair<Holder<PoiType>, BlockPos>> optional = level.getPoiManager().findClosestWithType(poiType, blockPos, 256, PoiManager.Occupancy.ANY);
|
||||
+ stopwatch.stop();
|
||||
+ if (optional.isEmpty()) {
|
||||
+ try {
|
||||
+ throw ERROR_POI_NOT_FOUND.create(poiType.asPrintable());
|
||||
+ } catch (CommandSyntaxException e) {
|
||||
+ source.sendFailure(Component.literal(e.getMessage()));
|
||||
+ }
|
||||
+ } else {
|
||||
+ showLocateResult(source, poiType, blockPos, optional.get().swap(), "commands.locate.poi.success", false, stopwatch.elapsed());
|
||||
+ }
|
||||
+ });
|
||||
+ return 0;
|
||||
+ // DivineMC end - Async poi locate
|
||||
}
|
||||
|
||||
public static int showLocateResult(
|
||||
@@ -195,7 +228,7 @@ public class LocateCommand {
|
||||
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.coordinates.tooltip")))
|
||||
);
|
||||
source.sendSuccess(() -> Component.translatable(translationKey, elementName, component, i), false);
|
||||
- LOGGER.info("Locating element " + elementName + " took " + duration.toMillis() + " ms");
|
||||
+ LOGGER.info("Locating element {} on Thread:{} took {} ms", elementName, Thread.currentThread().getName(), duration.toMillis()); // DivineMC - Log thread name
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -1,650 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Fri, 31 Jan 2025 21:50:46 +0300
|
||||
Subject: [PATCH] Misc Optimizations
|
||||
|
||||
|
||||
diff --git a/com/mojang/brigadier/tree/CommandNode.java b/com/mojang/brigadier/tree/CommandNode.java
|
||||
index 2ae5b80338282ac73c74765fc0729af2d54f6d6c..00a63a6a5983e6a25f2a9014a2f9eefeda468cdf 100644
|
||||
--- a/com/mojang/brigadier/tree/CommandNode.java
|
||||
+++ b/com/mojang/brigadier/tree/CommandNode.java
|
||||
@@ -24,7 +24,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
|
||||
- private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
|
||||
+ private final Map<String, CommandNode<S>> children = Collections.synchronizedMap(new LinkedHashMap<>()); // DivineMC - Misc Optimizations
|
||||
private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
|
||||
private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
|
||||
public Predicate<S> requirement; // Paper - public-f
|
||||
diff --git a/com/mojang/math/OctahedralGroup.java b/com/mojang/math/OctahedralGroup.java
|
||||
index 11902e7427761746ee098fea3276a34fef0096ba..3ba23fa243f7af712a41316066ca554f1c23b495 100644
|
||||
--- a/com/mojang/math/OctahedralGroup.java
|
||||
+++ b/com/mojang/math/OctahedralGroup.java
|
||||
@@ -112,6 +112,7 @@ public enum OctahedralGroup implements StringRepresentable {
|
||||
this.transformation = new Matrix3f().scaling(invertX ? -1.0F : 1.0F, invertY ? -1.0F : 1.0F, invertZ ? -1.0F : 1.0F);
|
||||
this.transformation.mul(permutation.transformation());
|
||||
this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
|
||||
+ this.rotate(Direction.UP); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
private BooleanList packInversions() {
|
||||
diff --git a/com/mojang/math/Transformation.java b/com/mojang/math/Transformation.java
|
||||
index aa755b8b7f8bc5910322e0c5b520f603da06a85a..e781dea43279aa77cc40a7afd2281c32cc8347a9 100644
|
||||
--- a/com/mojang/math/Transformation.java
|
||||
+++ b/com/mojang/math/Transformation.java
|
||||
@@ -51,6 +51,7 @@ public final class Transformation {
|
||||
} else {
|
||||
this.matrix = matrix;
|
||||
}
|
||||
+ ensureDecomposed(); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public Transformation(@Nullable Vector3f translation, @Nullable Quaternionf leftRotation, @Nullable Vector3f scale, @Nullable Quaternionf rightRotation) {
|
||||
@@ -60,6 +61,7 @@ public final class Transformation {
|
||||
this.scale = scale != null ? scale : new Vector3f(1.0F, 1.0F, 1.0F);
|
||||
this.rightRotation = rightRotation != null ? rightRotation : new Quaternionf();
|
||||
this.decomposed = true;
|
||||
+ ensureDecomposed(); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static Transformation identity() {
|
||||
diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java
|
||||
index 5f752603aa5611ce9d3dd44cc5b70c27ac46a86e..332122c0b700fb743f91f3fed16aade41dceec28 100644
|
||||
--- a/net/minecraft/core/MappedRegistry.java
|
||||
+++ b/net/minecraft/core/MappedRegistry.java
|
||||
@@ -34,10 +34,12 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
|
||||
private final ResourceKey<? extends Registry<T>> key;
|
||||
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
|
||||
private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(2048), map -> map.defaultReturnValue(-1)); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
- private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
- private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
- private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
- private final Map<ResourceKey<T>, RegistrationInfo> registrationInfos = new IdentityHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ private final Map<ResourceLocation, Holder.Reference<T>> byLocation = new java.util.concurrent.ConcurrentHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new java.util.concurrent.ConcurrentHashMap<>(2048); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<T, Holder.Reference<T>> byValue = Collections.synchronizedMap(new IdentityHashMap<>(2048)); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ private final Map<ResourceKey<T>, RegistrationInfo> registrationInfos = Collections.synchronizedMap(new IdentityHashMap<>(2048)); // Paper - Perf: Use bigger expected size to reduce collisions
|
||||
+ // DivineMC end - Some optimizations
|
||||
private Lifecycle registryLifecycle;
|
||||
private final Map<TagKey<T>, HolderSet.Named<T>> frozenTags = new IdentityHashMap<>();
|
||||
MappedRegistry.TagSet<T> allTags = MappedRegistry.TagSet.unbound();
|
||||
diff --git a/net/minecraft/server/level/ChunkTrackingView.java b/net/minecraft/server/level/ChunkTrackingView.java
|
||||
index bee90335677f7d8b01589ce5cfd81a40fd422886..a5e488d14fd2016ee188b114d0e681562b5b09cc 100644
|
||||
--- a/net/minecraft/server/level/ChunkTrackingView.java
|
||||
+++ b/net/minecraft/server/level/ChunkTrackingView.java
|
||||
@@ -73,12 +73,12 @@ public interface ChunkTrackingView {
|
||||
}
|
||||
|
||||
static boolean isWithinDistance(int centerX, int centerZ, int viewDistance, int x, int z, boolean includeOuterChunksAdjacentToViewBorder) {
|
||||
- int i = includeOuterChunksAdjacentToViewBorder ? 2 : 1;
|
||||
- long l = Math.max(0, Math.abs(x - centerX) - i);
|
||||
- long l1 = Math.max(0, Math.abs(z - centerZ) - i);
|
||||
- long l2 = l * l + l1 * l1;
|
||||
- int i1 = viewDistance * viewDistance;
|
||||
- return l2 < i1;
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ int actualViewDistance = viewDistance + (includeOuterChunksAdjacentToViewBorder ? 1 : 0);
|
||||
+ int xDistance = Math.abs(centerX - x);
|
||||
+ int zDistance = Math.abs(centerZ - z);
|
||||
+ return xDistance <= actualViewDistance && zDistance <= actualViewDistance;
|
||||
+ // DivineMC end - Some optimizations
|
||||
}
|
||||
|
||||
public record Positioned(ChunkPos center, int viewDistance) implements ChunkTrackingView {
|
||||
diff --git a/net/minecraft/util/ClassInstanceMultiMap.java b/net/minecraft/util/ClassInstanceMultiMap.java
|
||||
index 2a708ae0d5bb209650b525e3c56051f8b5655074..4c7670224f0c90c1d0d833ff0b3d908846133b4a 100644
|
||||
--- a/net/minecraft/util/ClassInstanceMultiMap.java
|
||||
+++ b/net/minecraft/util/ClassInstanceMultiMap.java
|
||||
@@ -14,9 +14,9 @@ import java.util.Map.Entry;
|
||||
import net.minecraft.Util;
|
||||
|
||||
public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
|
||||
- private final Map<Class<?>, List<T>> byClass = Maps.newHashMap();
|
||||
+ private final Map<Class<?>, List<T>> byClass = new it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap<>(); // DivineMC - Misc Optimizations
|
||||
private final Class<T> baseClass;
|
||||
- private final List<T> allInstances = Lists.newArrayList();
|
||||
+ private final List<T> allInstances = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(); // DivineMC - Misc Optimizations
|
||||
|
||||
public ClassInstanceMultiMap(Class<T> baseClass) {
|
||||
this.baseClass = baseClass;
|
||||
@@ -56,13 +56,27 @@ public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
|
||||
}
|
||||
|
||||
public <S> Collection<S> find(Class<S> type) {
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ List<T> cached = this.byClass.get(type);
|
||||
+ if (cached != null) return (Collection<S>) cached;
|
||||
+
|
||||
if (!this.baseClass.isAssignableFrom(type)) {
|
||||
throw new IllegalArgumentException("Don't know how to search for " + type);
|
||||
} else {
|
||||
- List<? extends T> list = this.byClass
|
||||
- .computeIfAbsent(type, clazz -> this.allInstances.stream().filter(clazz::isInstance).collect(Util.toMutableList()));
|
||||
- return (Collection<S>)Collections.unmodifiableCollection(list);
|
||||
+ List<? extends T> list = this.byClass.computeIfAbsent(type,
|
||||
+ typeClass -> {
|
||||
+ it.unimi.dsi.fastutil.objects.ObjectArrayList<T> ts = new it.unimi.dsi.fastutil.objects.ObjectArrayList<>(this.allInstances.size());
|
||||
+ for (Object _allElement : ((it.unimi.dsi.fastutil.objects.ObjectArrayList<T>) this.allInstances).elements()) {
|
||||
+ if (typeClass.isInstance(_allElement)) {
|
||||
+ ts.add((T) _allElement);
|
||||
+ }
|
||||
+ }
|
||||
+ return ts;
|
||||
+ }
|
||||
+ );
|
||||
+ return (Collection<S>) list;
|
||||
}
|
||||
+ // DivineMC end - Some optimizations
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java b/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java
|
||||
index f28fbf81a417a678726d3f77b3999054676d522e..7ff32b1f93b31fafd13f4e0857d14d85ef1f28c7 100644
|
||||
--- a/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java
|
||||
+++ b/net/minecraft/util/CrudeIncrementalIntIdentityHashBiMap.java
|
||||
@@ -52,23 +52,23 @@ public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K>, ca.spo
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
- public K byId(int value) {
|
||||
+ public synchronized K byId(int value) { // DivineMC - Misc Optimizations
|
||||
return value >= 0 && value < this.byId.length ? this.byId[value] : null;
|
||||
}
|
||||
|
||||
- private int getValue(int key) {
|
||||
+ private synchronized int getValue(int key) { // DivineMC - Misc Optimizations
|
||||
return key == -1 ? -1 : this.values[key];
|
||||
}
|
||||
|
||||
- public boolean contains(K value) {
|
||||
+ public synchronized boolean contains(K value) { // DivineMC - Misc Optimizations
|
||||
return this.getId(value) != -1;
|
||||
}
|
||||
|
||||
- public boolean contains(int value) {
|
||||
+ public synchronized boolean contains(int value) { // DivineMC - Misc Optimizations
|
||||
return this.byId(value) != null;
|
||||
}
|
||||
|
||||
- public int add(K object) {
|
||||
+ public synchronized int add(K object) { // DivineMC - Misc Optimizations
|
||||
int i = this.nextId();
|
||||
this.addMapping(object, i);
|
||||
return i;
|
||||
@@ -106,7 +106,7 @@ public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K>, ca.spo
|
||||
// Paper end - optimise palette reads
|
||||
}
|
||||
|
||||
- public void addMapping(K object, int intKey) {
|
||||
+ public synchronized void addMapping(K object, int intKey) { // DivineMC - Misc Optimizations
|
||||
int max = Math.max(intKey, this.size + 1);
|
||||
if (max >= this.keys.length * 0.8F) {
|
||||
int i = this.keys.length << 1;
|
||||
@@ -173,11 +173,11 @@ public class CrudeIncrementalIntIdentityHashBiMap<K> implements IdMap<K>, ca.spo
|
||||
}
|
||||
|
||||
@Override
|
||||
- public Iterator<K> iterator() {
|
||||
+ public synchronized Iterator<K> iterator() { // DivineMC - Misc Optimizations
|
||||
return Iterators.filter(Iterators.forArray(this.byId), Predicates.notNull());
|
||||
}
|
||||
|
||||
- public void clear() {
|
||||
+ public synchronized void clear() { // DivineMC - Misc Optimizations
|
||||
Arrays.fill(this.keys, null);
|
||||
Arrays.fill(this.byId, null);
|
||||
this.nextId = 0;
|
||||
diff --git a/net/minecraft/util/CubicSpline.java b/net/minecraft/util/CubicSpline.java
|
||||
index f36f8f2d49d4eba5c80eb243883749d6f831eb8a..5abd899c88683cb79bb8f02e43c4bfbe8563f496 100644
|
||||
--- a/net/minecraft/util/CubicSpline.java
|
||||
+++ b/net/minecraft/util/CubicSpline.java
|
||||
@@ -254,31 +254,47 @@ public interface CubicSpline<C, I extends ToFloatFunction<C>> extends ToFloatFun
|
||||
|
||||
@Override
|
||||
public float apply(C object) {
|
||||
- float f = this.coordinate.apply(object);
|
||||
- int i = findIntervalStart(this.locations, f);
|
||||
- int i1 = this.locations.length - 1;
|
||||
- if (i < 0) {
|
||||
- return linearExtend(f, this.locations, this.values.get(0).apply(object), this.derivatives, 0);
|
||||
- } else if (i == i1) {
|
||||
- return linearExtend(f, this.locations, this.values.get(i1).apply(object), this.derivatives, i1);
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ float point = this.coordinate.apply(object);
|
||||
+ int rangeForLocation = findIntervalStart(this.locations, point);
|
||||
+ int last = this.locations.length - 1;
|
||||
+ if (rangeForLocation < 0) {
|
||||
+ return linearExtend(point, this.locations, this.values.get(0).apply(object), this.derivatives, 0);
|
||||
+ } else if (rangeForLocation == last) {
|
||||
+ return linearExtend(point, this.locations, this.values.get(last).apply(object), this.derivatives, last);
|
||||
} else {
|
||||
- float f1 = this.locations[i];
|
||||
- float f2 = this.locations[i + 1];
|
||||
- float f3 = (f - f1) / (f2 - f1);
|
||||
- ToFloatFunction<C> toFloatFunction = (ToFloatFunction<C>)this.values.get(i);
|
||||
- ToFloatFunction<C> toFloatFunction1 = (ToFloatFunction<C>)this.values.get(i + 1);
|
||||
- float f4 = this.derivatives[i];
|
||||
- float f5 = this.derivatives[i + 1];
|
||||
- float f6 = toFloatFunction.apply(object);
|
||||
- float f7 = toFloatFunction1.apply(object);
|
||||
- float f8 = f4 * (f2 - f1) - (f7 - f6);
|
||||
- float f9 = -f5 * (f2 - f1) + (f7 - f6);
|
||||
- return Mth.lerp(f3, f6, f7) + f3 * (1.0F - f3) * Mth.lerp(f3, f8, f9);
|
||||
+ float loc0 = this.locations[rangeForLocation];
|
||||
+ float loc1 = this.locations[rangeForLocation + 1];
|
||||
+ float locDist = loc1 - loc0;
|
||||
+ float k = (point - loc0) / locDist;
|
||||
+ float n = this.values.get(rangeForLocation).apply(object);
|
||||
+ float o = this.values.get(rangeForLocation + 1).apply(object);
|
||||
+ float onDist = o - n;
|
||||
+ float p = this.derivatives[rangeForLocation] * locDist - onDist;
|
||||
+ float q = -this.derivatives[rangeForLocation + 1] * locDist + onDist;
|
||||
+ return Mth.lerp(k, n, o) + k * (1.0F - k) * Mth.lerp(k, p, q);
|
||||
}
|
||||
+ // DivineMC end - Some optimizations
|
||||
}
|
||||
|
||||
private static int findIntervalStart(float[] locations, float start) {
|
||||
- return Mth.binarySearch(0, locations.length, i -> start < locations[i]) - 1;
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ int min = 0;
|
||||
+ int i = locations.length;
|
||||
+
|
||||
+ while (i > 0) {
|
||||
+ int j = i / 2;
|
||||
+ int k = min + j;
|
||||
+ if (start < locations[k]) {
|
||||
+ i = j;
|
||||
+ } else {
|
||||
+ min = k + 1;
|
||||
+ i -= j + 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return min - 1;
|
||||
+ // DivineMC end - Some optimizations
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -313,5 +329,27 @@ public interface CubicSpline<C, I extends ToFloatFunction<C>> extends ToFloatFun
|
||||
this.derivatives
|
||||
);
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ @Override
|
||||
+ public boolean equals(Object o) {
|
||||
+ if (this == o) return true;
|
||||
+ if (o == null || getClass() != o.getClass()) return false;
|
||||
+ Multipoint<?, ?> that = (Multipoint<?, ?>) o;
|
||||
+ return java.util.Objects.equals(coordinate, that.coordinate()) && java.util.Arrays.equals(locations, that.locations()) && java.util.Objects.equals(values, that.values()) && java.util.Arrays.equals(derivatives, that.derivatives());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int hashCode() {
|
||||
+ int result = 1;
|
||||
+
|
||||
+ result = 31 * result + java.util.Objects.hashCode(coordinate);
|
||||
+ result = 31 * result + java.util.Arrays.hashCode(locations);
|
||||
+ result = 31 * result + java.util.Objects.hashCode(values);
|
||||
+ result = 31 * result + java.util.Arrays.hashCode(derivatives);
|
||||
+
|
||||
+ return result;
|
||||
+ }
|
||||
+ // DivineMC end - Some optimizations
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/util/Mth.java b/net/minecraft/util/Mth.java
|
||||
index ab3a221c115992d0f4ea921aa92cf0976b815ff4..076a931341da486162f289a5f19d3d6736df7768 100644
|
||||
--- a/net/minecraft/util/Mth.java
|
||||
+++ b/net/minecraft/util/Mth.java
|
||||
@@ -46,11 +46,11 @@ public class Mth {
|
||||
private static final double[] COS_TAB = new double[257];
|
||||
|
||||
public static float sin(float value) {
|
||||
- return SIN[(int)(value * 10430.378F) & 65535];
|
||||
+ return net.caffeinemc.mods.lithium.common.util.math.CompactSineLUT.sin(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static float cos(float value) {
|
||||
- return SIN[(int)(value * 10430.378F + 16384.0F) & 65535];
|
||||
+ return net.caffeinemc.mods.lithium.common.util.math.CompactSineLUT.cos(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static float sqrt(float value) {
|
||||
@@ -58,18 +58,15 @@ public class Mth {
|
||||
}
|
||||
|
||||
public static int floor(float value) {
|
||||
- int i = (int)value;
|
||||
- return value < i ? i - 1 : i;
|
||||
+ return (int) Math.floor(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static int floor(double value) {
|
||||
- int i = (int)value;
|
||||
- return value < i ? i - 1 : i;
|
||||
+ return (int) Math.floor(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static long lfloor(double value) {
|
||||
- long l = (long)value;
|
||||
- return value < l ? l - 1L : l;
|
||||
+ return (long) Math.floor(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static float abs(float value) {
|
||||
@@ -81,13 +78,11 @@ public class Mth {
|
||||
}
|
||||
|
||||
public static int ceil(float value) {
|
||||
- int i = (int)value;
|
||||
- return value > i ? i + 1 : i;
|
||||
+ return (int) Math.ceil(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static int ceil(double value) {
|
||||
- int i = (int)value;
|
||||
- return value > i ? i + 1 : i;
|
||||
+ return (int) Math.ceil(value); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static int clamp(int value, int min, int max) {
|
||||
@@ -123,15 +118,7 @@ public class Mth {
|
||||
}
|
||||
|
||||
public static double absMax(double x, double y) {
|
||||
- if (x < 0.0) {
|
||||
- x = -x;
|
||||
- }
|
||||
-
|
||||
- if (y < 0.0) {
|
||||
- y = -y;
|
||||
- }
|
||||
-
|
||||
- return Math.max(x, y);
|
||||
+ return Math.max(Math.abs(x), Math.abs(y)); // DivineMC - Math Optimizations
|
||||
}
|
||||
|
||||
public static int floorDiv(int dividend, int divisor) {
|
||||
@@ -162,14 +149,26 @@ public class Mth {
|
||||
return Math.floorMod(x, y);
|
||||
}
|
||||
|
||||
- public static float positiveModulo(float numerator, float denominator) {
|
||||
+ public static float positiveModuloForAnyDenominator(float numerator, float denominator) { // DivineMC - Math Optimizations
|
||||
return (numerator % denominator + denominator) % denominator;
|
||||
}
|
||||
|
||||
- public static double positiveModulo(double numerator, double denominator) {
|
||||
+ public static double positiveModuloForAnyDenominator(double numerator, double denominator) { // DivineMC - Math Optimizations
|
||||
return (numerator % denominator + denominator) % denominator;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Math Optimizations
|
||||
+ public static float positiveModuloForPositiveIntegerDenominator(float numerator, float denominator) {
|
||||
+ var modulo = numerator % denominator;
|
||||
+ return modulo < 0 ? modulo + denominator : modulo;
|
||||
+ }
|
||||
+
|
||||
+ public static double positiveModuloForPositiveIntegerDenominator(double numerator, double denominator) {
|
||||
+ var modulo = numerator % denominator;
|
||||
+ return modulo < 0 ? modulo + denominator : modulo;
|
||||
+ }
|
||||
+ // DivineMC end - Math Optimizations
|
||||
+
|
||||
public static boolean isMultipleOf(int number, int multiple) {
|
||||
return number % multiple == 0;
|
||||
}
|
||||
diff --git a/net/minecraft/util/RandomSource.java b/net/minecraft/util/RandomSource.java
|
||||
index 98a54bc4de251014342cda6d0951b7fea79ce553..663edee4dfa660e3d3a04c728fd764258867916d 100644
|
||||
--- a/net/minecraft/util/RandomSource.java
|
||||
+++ b/net/minecraft/util/RandomSource.java
|
||||
@@ -12,7 +12,7 @@ public interface RandomSource {
|
||||
double GAUSSIAN_SPREAD_FACTOR = 2.297;
|
||||
|
||||
static RandomSource create() {
|
||||
- return create(RandomSupport.generateUniqueSeed());
|
||||
+ return createThreadSafe(); // DivineMC - Misc Optimizations
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -21,7 +21,7 @@ public interface RandomSource {
|
||||
}
|
||||
|
||||
static RandomSource create(long seed) {
|
||||
- return new LegacyRandomSource(seed);
|
||||
+ return new ThreadSafeLegacyRandomSource(seed); // DivineMC - Misc Optimizations
|
||||
}
|
||||
|
||||
static RandomSource createNewThreadLocalInstance() {
|
||||
diff --git a/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java b/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java
|
||||
index 15de39fa82c7aea18298509fe9587d027c30cc15..eb534ed5a7478fc632db096328e3582f4ec410b8 100644
|
||||
--- a/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java
|
||||
+++ b/net/minecraft/util/debugchart/DebugSampleSubscriptionTracker.java
|
||||
@@ -15,7 +15,7 @@ public class DebugSampleSubscriptionTracker {
|
||||
public static final int STOP_SENDING_AFTER_MS = 10000;
|
||||
private final PlayerList playerList;
|
||||
private final EnumMap<RemoteDebugSampleType, Map<ServerPlayer, DebugSampleSubscriptionTracker.SubscriptionStartedAt>> subscriptions;
|
||||
- private final Queue<DebugSampleSubscriptionTracker.SubscriptionRequest> subscriptionRequestQueue = new LinkedList<>();
|
||||
+ private final java.util.List<SubscriptionRequest> subscriptionRequestQueue = java.util.Collections.synchronizedList(new LinkedList<>()); // DivineMC - Misc Optimizations
|
||||
|
||||
public DebugSampleSubscriptionTracker(PlayerList playerList) {
|
||||
this.playerList = playerList;
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 258cb45f1f959b75c1bcdb130811af2f8fddf07d..9c0e539f09bddac018f93d212e3cdbc446f3c672 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -143,7 +143,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
// Paper start - Share random for entities to make them more random
|
||||
- public static RandomSource SHARED_RANDOM = new RandomRandomSource();
|
||||
+ public static RandomSource SHARED_RANDOM = new net.minecraft.world.level.levelgen.ThreadSafeLegacyRandomSource(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // DivineMC - Misc Optimizations
|
||||
// Paper start - replace random
|
||||
private static final class RandomRandomSource extends ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom {
|
||||
public RandomRandomSource() {
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index 66f3565b978f2ed91cb2bc3a816f1701c0873c73..b4e19cc65701d5ef94e1cc0a7473225c222725c3 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -832,7 +832,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
|
||||
this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
} else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) {
|
||||
- Entity nearestPlayer = this.level().findNearbyPlayer(this, -1.0, EntitySelector.PLAYER_AFFECTS_SPAWNING); // Paper - Affects Spawning API
|
||||
+ Entity nearestPlayer = this.divinemc$findNearbyPlayer(this.level(), this, -1.0); // Paper - Affects Spawning API // DivineMC - faster player lookup
|
||||
if (nearestPlayer != null) {
|
||||
// Paper start - Configurable despawn distances
|
||||
final io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DespawnRangePair despawnRangePair = this.level().paperConfig().entities.spawning.despawnRanges.get(this.getType().getCategory());
|
||||
@@ -861,6 +861,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - faster player lookup
|
||||
+ private Player divinemc$findNearbyPlayer(Level instance, Entity entity, double maxDistance) {
|
||||
+ final Player closestPlayer = instance.getNearestPlayer(entity, this.getType().getCategory().getDespawnDistance());
|
||||
+ if (closestPlayer != null) {
|
||||
+ return closestPlayer;
|
||||
+ } else {
|
||||
+ final List<? extends Player> players = this.level().players();
|
||||
+ if (players.isEmpty()) return null;
|
||||
+ return players.get(0);
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - faster player lookup
|
||||
+
|
||||
@Override
|
||||
protected final void serverAiStep() {
|
||||
this.noActionTime++;
|
||||
diff --git a/net/minecraft/world/level/GameRules.java b/net/minecraft/world/level/GameRules.java
|
||||
index 5ded2f808a9fcb26856567de6bc56e206f948a84..02d64a5ea756b2c91a71b7a0fc0f21219983616a 100644
|
||||
--- a/net/minecraft/world/level/GameRules.java
|
||||
+++ b/net/minecraft/world/level/GameRules.java
|
||||
@@ -249,7 +249,7 @@ public class GameRules {
|
||||
}
|
||||
|
||||
private GameRules(Map<GameRules.Key<?>, GameRules.Value<?>> rules, FeatureFlagSet enabledFeatures) {
|
||||
- this.rules = rules;
|
||||
+ this.rules = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(rules); // DivineMC - lithium: collections.gamerules
|
||||
this.enabledFeatures = enabledFeatures;
|
||||
|
||||
// Paper start - Perf: Use array for gamerule storage
|
||||
diff --git a/net/minecraft/world/level/LocalMobCapCalculator.java b/net/minecraft/world/level/LocalMobCapCalculator.java
|
||||
index 9641219c190261dea0db5f95f040a705ba0a3ff9..a3fccdeb2c076e12b611683da55d45e00a166417 100644
|
||||
--- a/net/minecraft/world/level/LocalMobCapCalculator.java
|
||||
+++ b/net/minecraft/world/level/LocalMobCapCalculator.java
|
||||
@@ -13,16 +13,24 @@ import net.minecraft.world.entity.MobCategory;
|
||||
|
||||
public class LocalMobCapCalculator {
|
||||
private final Long2ObjectMap<List<ServerPlayer>> playersNearChunk = new Long2ObjectOpenHashMap<>();
|
||||
- private final Map<ServerPlayer, LocalMobCapCalculator.MobCounts> playerMobCounts = Maps.newHashMap();
|
||||
+ private final Map<ServerPlayer, LocalMobCapCalculator.MobCounts> playerMobCounts = Maps.newConcurrentMap(); // DivineMC - Misc Optimizations
|
||||
private final ChunkMap chunkMap;
|
||||
|
||||
public LocalMobCapCalculator(ChunkMap chunkMap) {
|
||||
this.chunkMap = chunkMap;
|
||||
}
|
||||
|
||||
- private List<ServerPlayer> getPlayersNear(ChunkPos pos) {
|
||||
- return this.playersNearChunk.computeIfAbsent(pos.toLong(), key -> this.chunkMap.getPlayersCloseForSpawning(pos));
|
||||
+ // DivineMC start - Some optimizations
|
||||
+ private synchronized @org.jetbrains.annotations.NotNull List<ServerPlayer> getPlayersNear(ChunkPos pos) {
|
||||
+ List<ServerPlayer> retVal = this.playersNearChunk.get(pos.toLong());
|
||||
+ if (retVal == null) {
|
||||
+ List<ServerPlayer> newVal = this.chunkMap.getPlayersCloseForSpawning(pos);
|
||||
+ this.playersNearChunk.put(pos.toLong(), newVal);
|
||||
+ return newVal;
|
||||
+ }
|
||||
+ return retVal;
|
||||
}
|
||||
+ // DivineMC end - Some optimizations
|
||||
|
||||
public void addMob(ChunkPos pos, MobCategory category) {
|
||||
for (ServerPlayer serverPlayer : this.getPlayersNear(pos)) {
|
||||
@@ -42,14 +50,14 @@ public class LocalMobCapCalculator {
|
||||
}
|
||||
|
||||
static class MobCounts {
|
||||
- private final Object2IntMap<MobCategory> counts = new Object2IntOpenHashMap<>(MobCategory.values().length);
|
||||
+ private final int[] spawnGroupDensities = new int[MobCategory.values().length]; // DivineMC - Misc Optimizations
|
||||
|
||||
public void add(MobCategory category) {
|
||||
- this.counts.computeInt(category, (key, value) -> value == null ? 1 : value + 1);
|
||||
+ this.spawnGroupDensities[category.ordinal()] ++; // DivineMC - Misc Optimizations
|
||||
}
|
||||
|
||||
public boolean canSpawn(MobCategory category) {
|
||||
- return this.counts.getOrDefault(category, 0) < category.getMaxInstancesPerChunk();
|
||||
+ return this.spawnGroupDensities[category.ordinal()] < category.getMaxInstancesPerChunk(); // DivineMC - Misc Optimizations
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/levelgen/blending/Blender.java b/net/minecraft/world/level/levelgen/blending/Blender.java
|
||||
index 01e5b29d6e9a5c53c0e23b61ed0c1d7be1a0fe08..d80df05e40f3941ade5ed320e12f8dcf47e6b247 100644
|
||||
--- a/net/minecraft/world/level/levelgen/blending/Blender.java
|
||||
+++ b/net/minecraft/world/level/levelgen/blending/Blender.java
|
||||
@@ -144,7 +144,7 @@ public class Blender {
|
||||
private static double heightToOffset(double height) {
|
||||
double d = 1.0;
|
||||
double d1 = height + 0.5;
|
||||
- double d2 = Mth.positiveModulo(d1, 8.0);
|
||||
+ double d2 = Mth.positiveModuloForPositiveIntegerDenominator(d1, 8.0); // DivineMC - Math optimizations
|
||||
return 1.0 * (32.0 * (d1 - 128.0) - 3.0 * (d1 - 120.0) * d2 + 3.0 * d2 * d2) / (128.0 * (32.0 - 3.0 * d2));
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
index 681dec447486138088fe5f705ef4fadab531139f..12ea268eaec629fde20d55460e618fde3a3e006d 100644
|
||||
--- a/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
+++ b/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java
|
||||
@@ -198,6 +198,7 @@ public class MapItemSavedData extends SavedData {
|
||||
}
|
||||
}
|
||||
|
||||
+ mapItemSavedData.setDirty(false); // DivineMC - Misc Optimizations
|
||||
return mapItemSavedData;
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/storage/DimensionDataStorage.java b/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
index d9a3b5a2e6495b7e22c114506c2bd1e406f58f8f..a6e03345afd6d8a38e06a43c59103209618baa14 100644
|
||||
--- a/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
+++ b/net/minecraft/world/level/storage/DimensionDataStorage.java
|
||||
@@ -34,7 +34,7 @@ import org.slf4j.Logger;
|
||||
|
||||
public class DimensionDataStorage implements AutoCloseable {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- public final Map<String, Optional<SavedData>> cache = new HashMap<>();
|
||||
+ public final Map<String, Optional<SavedData>> cache = new java.util.concurrent.ConcurrentHashMap<>(); // DivineMC - Concurrent HashMap
|
||||
private final DataFixer fixerUpper;
|
||||
private final HolderLookup.Provider registries;
|
||||
private final Path dataFolder;
|
||||
diff --git a/net/minecraft/world/phys/AABB.java b/net/minecraft/world/phys/AABB.java
|
||||
index c9c6e4e460ad8435f12761704bb9b0284d6aa708..54807bb4b4189ceaded1f78a1a9ab85ce40ab2b1 100644
|
||||
--- a/net/minecraft/world/phys/AABB.java
|
||||
+++ b/net/minecraft/world/phys/AABB.java
|
||||
@@ -189,13 +189,15 @@ public class AABB {
|
||||
}
|
||||
|
||||
public AABB intersect(AABB other) {
|
||||
- double max = Math.max(this.minX, other.minX);
|
||||
- double max1 = Math.max(this.minY, other.minY);
|
||||
- double max2 = Math.max(this.minZ, other.minZ);
|
||||
- double min = Math.min(this.maxX, other.maxX);
|
||||
- double min1 = Math.min(this.maxY, other.maxY);
|
||||
- double min2 = Math.min(this.maxZ, other.maxZ);
|
||||
- return new AABB(max, max1, max2, min, min1, min2);
|
||||
+ // DivineMC start - Math Optimizations
|
||||
+ return new AABB(
|
||||
+ this.minX > other.minX ? this.minX : other.minX,
|
||||
+ this.minY > other.minY ? this.minY : other.minY,
|
||||
+ this.minZ > other.minZ ? this.minZ : other.minZ,
|
||||
+ this.maxX < other.maxX ? this.maxX : other.maxX,
|
||||
+ this.maxY < other.maxY ? this.maxY : other.maxY,
|
||||
+ this.maxZ < other.maxZ ? this.maxZ : other.maxZ
|
||||
+ );
|
||||
}
|
||||
|
||||
public AABB minmax(AABB other) {
|
||||
@@ -227,16 +229,37 @@ public class AABB {
|
||||
}
|
||||
|
||||
public boolean intersects(AABB other) {
|
||||
- return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ);
|
||||
+ // DivineMC start - Math Optimizations
|
||||
+ return this.minX < other.maxX &&
|
||||
+ this.maxX > other.minX &&
|
||||
+ this.minY < other.maxY &&
|
||||
+ this.maxY > other.minY &&
|
||||
+ this.minZ < other.maxZ &&
|
||||
+ this.maxZ > other.minZ;
|
||||
+ // DivineMC end - Math Optimizations
|
||||
}
|
||||
|
||||
public boolean intersects(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
- return this.minX < x2 && this.maxX > x1 && this.minY < y2 && this.maxY > y1 && this.minZ < z2 && this.maxZ > z1;
|
||||
+ // DivineMC start - Math Optimizations
|
||||
+ return this.minX < x2 &&
|
||||
+ this.maxX > x1 &&
|
||||
+ this.minY < y2 &&
|
||||
+ this.maxY > y1 &&
|
||||
+ this.minZ < z2 &&
|
||||
+ this.maxZ > z1;
|
||||
+ // DivineMC end - Math Optimizations
|
||||
}
|
||||
|
||||
public boolean intersects(Vec3 min, Vec3 max) {
|
||||
return this.intersects(
|
||||
- Math.min(min.x, max.x), Math.min(min.y, max.y), Math.min(min.z, max.z), Math.max(min.x, max.x), Math.max(min.y, max.y), Math.max(min.z, max.z)
|
||||
+ // DivineMC start - Math Optimizations
|
||||
+ min.x < max.x ? min.x : max.x,
|
||||
+ min.y < max.y ? min.y : max.y,
|
||||
+ min.z < max.z ? min.z : max.z,
|
||||
+ min.x > max.x ? min.x : max.x,
|
||||
+ min.y > max.y ? min.y : max.y,
|
||||
+ min.z > max.z ? min.z : max.z
|
||||
+ // DivineMC end - Math Optimizations
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,145 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Fri, 31 Jan 2025 22:40:54 +0300
|
||||
Subject: [PATCH] Optimize Fluids
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/LiquidBlock.java b/net/minecraft/world/level/block/LiquidBlock.java
|
||||
index 47a7ce88bf4d26408545dcc061aa763311af0dc9..13877d2bd4289652a9627780839b8d879a66d753 100644
|
||||
--- a/net/minecraft/world/level/block/LiquidBlock.java
|
||||
+++ b/net/minecraft/world/level/block/LiquidBlock.java
|
||||
@@ -193,6 +193,7 @@ public class LiquidBlock extends Block implements BucketPickup {
|
||||
Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) {
|
||||
+ level.setBlock(pos, block.defaultBlockState(), 3); // DivineMC - Optimize Fluids
|
||||
this.fizz(level, pos);
|
||||
}
|
||||
// CraftBukkit end
|
||||
diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java
|
||||
index 44bc0823e163bb7edee27889201ec76e93e095cf..974e1e5dcb2613c5aaedd3f2f66483c9dcd6cd23 100644
|
||||
--- a/net/minecraft/world/level/material/FlowingFluid.java
|
||||
+++ b/net/minecraft/world/level/material/FlowingFluid.java
|
||||
@@ -199,6 +199,7 @@ public abstract class FlowingFluid extends Fluid {
|
||||
BlockPos blockPos = pos.relative(direction);
|
||||
final BlockState blockStateIfLoaded = level.getBlockStateIfLoaded(blockPos); // Paper - Prevent chunk loading from fluid flowing
|
||||
if (blockStateIfLoaded == null) continue; // Paper - Prevent chunk loading from fluid flowing
|
||||
+ if (!shouldSpreadLiquid(level, blockPos, blockStateIfLoaded)) continue; // DivineMC - Optimize Fluids
|
||||
// CraftBukkit start
|
||||
org.bukkit.block.Block source = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
org.bukkit.event.block.BlockFromToEvent event = new org.bukkit.event.block.BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(direction));
|
||||
@@ -213,6 +214,39 @@ public abstract class FlowingFluid extends Fluid {
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize Fluids
|
||||
+ private boolean shouldSpreadLiquid(Level level, BlockPos pos, BlockState state) {
|
||||
+ if (state.is(Blocks.LAVA)) {
|
||||
+ boolean isSoulSoil = level.getBlockState(pos.below()).is(Blocks.SOUL_SOIL);
|
||||
+
|
||||
+ for (Direction direction : net.minecraft.world.level.block.LiquidBlock.POSSIBLE_FLOW_DIRECTIONS) {
|
||||
+ BlockPos blockPos = pos.relative(direction.getOpposite());
|
||||
+ if (level.getFluidState(blockPos).is(net.minecraft.tags.FluidTags.WATER)) {
|
||||
+ Block block = level.getFluidState(pos).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE;
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState())) {
|
||||
+ this.fizz(level, pos);
|
||||
+ level.setBlock(pos, block.defaultBlockState(), 3);
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (isSoulSoil && level.getBlockState(blockPos).is(Blocks.BLUE_ICE)) {
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, Blocks.BASALT.defaultBlockState())) {
|
||||
+ this.fizz(level, pos);
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ private void fizz(LevelAccessor level, BlockPos pos) {
|
||||
+ level.levelEvent(1501, pos, 0);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Fluids
|
||||
+
|
||||
protected FluidState getNewLiquid(ServerLevel level, BlockPos pos, BlockState state) {
|
||||
int i = 0;
|
||||
int i1 = 0;
|
||||
@@ -341,33 +375,46 @@ public abstract class FlowingFluid extends Fluid {
|
||||
protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state, BlockPos source) { beforeDestroyingBlock(level, pos, state); } // Paper - Add BlockBreakBlockEvent
|
||||
protected abstract void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state);
|
||||
|
||||
+ // DivineMC start - Optimize Fluids
|
||||
protected int getSlopeDistance(LevelReader level, BlockPos pos, int depth, Direction direction, BlockState state, FlowingFluid.SpreadContext spreadContext) {
|
||||
- int i = 1000;
|
||||
+ int slopeFindDistance = this.getSlopeFindDistance(level);
|
||||
+ int minDistance = slopeFindDistance;
|
||||
|
||||
- for (Direction direction1 : Direction.Plane.HORIZONTAL) {
|
||||
- if (direction1 != direction) {
|
||||
- BlockPos blockPos = pos.relative(direction1);
|
||||
- BlockState blockState = spreadContext.getBlockStateIfLoaded(blockPos); // Paper - Prevent chunk loading from fluid flowing
|
||||
- if (blockState == null) continue; // Paper - Prevent chunk loading from fluid flowing
|
||||
- FluidState fluidState = blockState.getFluidState();
|
||||
- if (this.canPassThrough(level, this.getFlowing(), pos, state, direction1, blockPos, blockState, fluidState)) {
|
||||
- if (spreadContext.isHole(blockPos)) {
|
||||
- return depth;
|
||||
+ java.util.Deque<net.minecraft.world.level.material.FlowingFluid.Node> stack = new java.util.ArrayDeque<>();
|
||||
+ stack.push(new Node(pos, depth, direction));
|
||||
+
|
||||
+ while (!stack.isEmpty()) {
|
||||
+ Node current = stack.pop();
|
||||
+ BlockPos currentPos = current.pos;
|
||||
+ int currentDepth = current.depth;
|
||||
+ Direction fromDirection = current.direction;
|
||||
+
|
||||
+ for (Direction dir : Direction.Plane.HORIZONTAL) {
|
||||
+ if (dir == fromDirection) continue;
|
||||
+
|
||||
+ BlockPos neighborPos = currentPos.relative(dir);
|
||||
+ BlockState neighborState = spreadContext.getBlockStateIfLoaded(neighborPos);
|
||||
+ if (neighborState == null) continue; // Prevent chunk loading
|
||||
+
|
||||
+ FluidState fluidState = neighborState.getFluidState();
|
||||
+ if (this.canPassThrough(level, this.getFlowing(), currentPos, state, dir, neighborPos, neighborState, fluidState)) {
|
||||
+ if (spreadContext.isHole(neighborPos)) {
|
||||
+ return currentDepth;
|
||||
}
|
||||
|
||||
- if (depth < this.getSlopeFindDistance(level)) {
|
||||
- int slopeDistance = this.getSlopeDistance(level, blockPos, depth + 1, direction1.getOpposite(), blockState, spreadContext);
|
||||
- if (slopeDistance < i) {
|
||||
- i = slopeDistance;
|
||||
- }
|
||||
+ if (currentDepth + 1 < slopeFindDistance && currentDepth + 1 < minDistance) {
|
||||
+ stack.push(new Node(neighborPos, currentDepth + 1, dir.getOpposite()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- return i;
|
||||
+ return minDistance;
|
||||
}
|
||||
|
||||
+ private record Node(BlockPos pos, int depth, Direction direction) { }
|
||||
+ // DivineMC end - Optimize Fluids
|
||||
+
|
||||
boolean isWaterHole(BlockGetter level, BlockPos pos, BlockState state, BlockPos belowPos, BlockState belowState) {
|
||||
return canPassThroughWall(Direction.DOWN, level, pos, state, belowPos, belowState)
|
||||
&& (belowState.getFluidState().getType().isSame(this) || canHoldFluid(level, belowPos, belowState, this.getFlowing()));
|
||||
diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java
|
||||
index 85629a43f5469a89dd6078d879f475e8212438ec..35b5a33c79c883f28c99c992695b188524593b55 100644
|
||||
--- a/net/minecraft/world/level/material/LavaFluid.java
|
||||
+++ b/net/minecraft/world/level/material/LavaFluid.java
|
||||
@@ -224,6 +224,7 @@ public abstract class LavaFluid extends FlowingFluid {
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ level.setBlock(pos, Blocks.STONE.defaultBlockState(), 3); // DivineMC - Optimize Fluids
|
||||
this.fizz(level, pos);
|
||||
return;
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 16:05:57 +0300
|
||||
Subject: [PATCH] Optimize entity stupid brain
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/AgeableMob.java b/net/minecraft/world/entity/AgeableMob.java
|
||||
index 179f4e4b9b1eb57f78bbb2f9fa34b11ea79b7a88..143a4ca51a57934bf545e031b10525dedbe9c3bd 100644
|
||||
--- a/net/minecraft/world/entity/AgeableMob.java
|
||||
+++ b/net/minecraft/world/entity/AgeableMob.java
|
||||
@@ -121,6 +121,16 @@ public abstract class AgeableMob extends PathfinderMob {
|
||||
public void onSyncedDataUpdated(EntityDataAccessor<?> key) {
|
||||
if (DATA_BABY_ID.equals(key)) {
|
||||
this.refreshDimensions();
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ if (isBaby()) {
|
||||
+ org.bxteam.divinemc.util.entity.SensorHelper.enableSensor(this, net.minecraft.world.entity.ai.sensing.SensorType.NEAREST_ADULT, true);
|
||||
+ } else {
|
||||
+ org.bxteam.divinemc.util.entity.SensorHelper.disableSensor(this, net.minecraft.world.entity.ai.sensing.SensorType.NEAREST_ADULT);
|
||||
+ if (this.getBrain().hasMemoryValue(net.minecraft.world.entity.ai.memory.MemoryModuleType.NEAREST_VISIBLE_ADULT)) {
|
||||
+ this.getBrain().setMemory(net.minecraft.world.entity.ai.memory.MemoryModuleType.NEAREST_VISIBLE_ADULT, java.util.Optional.empty());
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
}
|
||||
|
||||
super.onSyncedDataUpdated(key);
|
||||
diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java
|
||||
index 8f7efe6b2c191f615dfc8394baec44dc0761ff51..406eb049cb22d0736d8b003a2f547cc25c6f68b6 100644
|
||||
--- a/net/minecraft/world/entity/ai/Brain.java
|
||||
+++ b/net/minecraft/world/entity/ai/Brain.java
|
||||
@@ -45,16 +45,73 @@ public class Brain<E extends LivingEntity> {
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final Supplier<Codec<Brain<E>>> codec;
|
||||
private static final int SCHEDULE_UPDATE_DELAY = 20;
|
||||
- private final Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = Maps.newHashMap();
|
||||
- public final Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap();
|
||||
- private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = Maps.newTreeMap();
|
||||
+ private Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = Maps.newConcurrentMap(); // DivineMC - concurrent map
|
||||
+ public Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = Maps.newLinkedHashMap(); // DivineMC - linked hash map
|
||||
+ private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = Maps.newTreeMap(); // DivineMC - tree map
|
||||
private Schedule schedule = Schedule.EMPTY;
|
||||
- private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap();
|
||||
+ private Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap(); // DivineMC - hash map
|
||||
private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = Maps.newHashMap();
|
||||
private Set<Activity> coreActivities = Sets.newHashSet();
|
||||
private final Set<Activity> activeActivities = Sets.newHashSet();
|
||||
private Activity defaultActivity = Activity.IDLE;
|
||||
private long lastScheduleUpdate = -9999L;
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ private java.util.ArrayList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> possibleTasks;
|
||||
+ private org.bxteam.divinemc.util.collections.MaskedList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> runningTasks;
|
||||
+
|
||||
+ private void onTasksChanged() {
|
||||
+ this.runningTasks = null;
|
||||
+ this.onPossibleActivitiesChanged();
|
||||
+ }
|
||||
+
|
||||
+ private void onPossibleActivitiesChanged() {
|
||||
+ this.possibleTasks = null;
|
||||
+ }
|
||||
+
|
||||
+ private void initPossibleTasks() {
|
||||
+ this.possibleTasks = new java.util.ArrayList<>();
|
||||
+ for (Map<Activity, Set<BehaviorControl<? super E>>> map : this.availableBehaviorsByPriority.values()) {
|
||||
+ for (Map.Entry<Activity, Set<BehaviorControl<? super E>>> entry : map.entrySet()) {
|
||||
+ Activity activity = entry.getKey();
|
||||
+ if (!this.activeActivities.contains(activity)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ Set<BehaviorControl<? super E>> set = entry.getValue();
|
||||
+ for (BehaviorControl<? super E> task : set) {
|
||||
+ //noinspection UseBulkOperation
|
||||
+ this.possibleTasks.add(task);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private java.util.ArrayList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> getPossibleTasks() {
|
||||
+ if (this.possibleTasks == null) {
|
||||
+ this.initPossibleTasks();
|
||||
+ }
|
||||
+ return this.possibleTasks;
|
||||
+ }
|
||||
+
|
||||
+ private org.bxteam.divinemc.util.collections.MaskedList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> getCurrentlyRunningTasks() {
|
||||
+ if (this.runningTasks == null) {
|
||||
+ this.initCurrentlyRunningTasks();
|
||||
+ }
|
||||
+ return this.runningTasks;
|
||||
+ }
|
||||
+
|
||||
+ private void initCurrentlyRunningTasks() {
|
||||
+ org.bxteam.divinemc.util.collections.MaskedList<net.minecraft.world.entity.ai.behavior.BehaviorControl<? super E>> list = new org.bxteam.divinemc.util.collections.MaskedList<>(new ObjectArrayList<>(), false);
|
||||
+
|
||||
+ for (Map<Activity, Set<BehaviorControl<? super E>>> map : this.availableBehaviorsByPriority.values()) {
|
||||
+ for (Set<BehaviorControl<? super E>> set : map.values()) {
|
||||
+ for (BehaviorControl<? super E> task : set) {
|
||||
+ list.addOrSet(task, task.getStatus() == Behavior.Status.RUNNING);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ this.runningTasks = list;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
|
||||
public static <E extends LivingEntity> Brain.Provider<E> provider(
|
||||
Collection<? extends MemoryModuleType<?>> memoryTypes, Collection<? extends SensorType<? extends Sensor<? super E>>> sensorTypes
|
||||
@@ -146,6 +203,12 @@ public class Brain<E extends LivingEntity> {
|
||||
for (Brain.MemoryValue<?> memoryValue : memoryValues) {
|
||||
memoryValue.setMemoryInternal(this);
|
||||
}
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ this.onTasksChanged();
|
||||
+ this.memories = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(this.memories);
|
||||
+ this.sensors = new it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap<>(this.sensors);
|
||||
+ this.activityRequirements = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.activityRequirements);
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
}
|
||||
|
||||
public <T> DataResult<T> serializeStart(DynamicOps<T> ops) {
|
||||
@@ -165,6 +228,7 @@ public class Brain<E extends LivingEntity> {
|
||||
}
|
||||
|
||||
public <U> void eraseMemory(MemoryModuleType<U> type) {
|
||||
+ if (!this.memories.containsKey(type)) return; // DivineMC - skip if memory does not contain key
|
||||
this.setMemory(type, Optional.empty());
|
||||
}
|
||||
|
||||
@@ -180,16 +244,33 @@ public class Brain<E extends LivingEntity> {
|
||||
this.setMemoryInternal(memoryType, memory.map(ExpirableValue::of));
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
<U> void setMemoryInternal(MemoryModuleType<U> memoryType, Optional<? extends ExpirableValue<?>> memory) {
|
||||
+ if (memory.isPresent() && this.isEmptyCollection(memory.get().getValue())) {
|
||||
+ this.eraseMemory(memoryType);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (this.memories.containsKey(memoryType)) {
|
||||
- if (memory.isPresent() && this.isEmptyCollection(memory.get().getValue())) {
|
||||
- this.eraseMemory(memoryType);
|
||||
- } else {
|
||||
- this.memories.put(memoryType, memory);
|
||||
- }
|
||||
+ this.increaseMemoryModificationCount(this.memories, memoryType, memory);
|
||||
}
|
||||
}
|
||||
|
||||
+ private long memoryModCount = 1;
|
||||
+
|
||||
+ public long getMemoryModCount() {
|
||||
+ return memoryModCount;
|
||||
+ }
|
||||
+
|
||||
+ private <T, A> Object increaseMemoryModificationCount(Map<T, A> map, T key, A newValue) {
|
||||
+ Object oldValue = map.put(key, newValue);
|
||||
+ if (oldValue == null || ((Optional<?>) oldValue).isPresent() != ((Optional<?>) newValue).isPresent()) {
|
||||
+ this.memoryModCount++;
|
||||
+ }
|
||||
+ return oldValue;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
+
|
||||
public <U> Optional<U> getMemory(MemoryModuleType<U> type) {
|
||||
Optional<? extends ExpirableValue<?>> optional = this.memories.get(type);
|
||||
if (optional == null) {
|
||||
@@ -251,19 +332,7 @@ public class Brain<E extends LivingEntity> {
|
||||
@Deprecated
|
||||
@VisibleForDebug
|
||||
public List<BehaviorControl<? super E>> getRunningBehaviors() {
|
||||
- List<BehaviorControl<? super E>> list = new ObjectArrayList<>();
|
||||
-
|
||||
- for (Map<Activity, Set<BehaviorControl<? super E>>> map : this.availableBehaviorsByPriority.values()) {
|
||||
- for (Set<BehaviorControl<? super E>> set : map.values()) {
|
||||
- for (BehaviorControl<? super E> behaviorControl : set) {
|
||||
- if (behaviorControl.getStatus() == Behavior.Status.RUNNING) {
|
||||
- list.add(behaviorControl);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return list;
|
||||
+ return this.getCurrentlyRunningTasks(); // DivineMC - Optimize entity stupid brain
|
||||
}
|
||||
|
||||
public void useDefaultActivity() {
|
||||
@@ -294,6 +363,7 @@ public class Brain<E extends LivingEntity> {
|
||||
this.activeActivities.clear();
|
||||
this.activeActivities.addAll(this.coreActivities);
|
||||
this.activeActivities.add(activity);
|
||||
+ this.onPossibleActivitiesChanged(); // DivineMC - Optimize entity stupid brain
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,11 +444,13 @@ public class Brain<E extends LivingEntity> {
|
||||
.computeIfAbsent(activity, activity1 -> Sets.newLinkedHashSet())
|
||||
.add((BehaviorControl<? super E>)pair.getSecond());
|
||||
}
|
||||
+ this.onTasksChanged(); // DivineMC - Optimize entity stupid brain
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void removeAllBehaviors() {
|
||||
this.availableBehaviorsByPriority.clear();
|
||||
+ this.onTasksChanged(); // DivineMC - Optimize entity stupid brain
|
||||
}
|
||||
|
||||
public boolean isActive(Activity activity) {
|
||||
@@ -395,6 +467,7 @@ public class Brain<E extends LivingEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
+ brain.memoryModCount = this.memoryModCount + 1; // DivineMC - Optimize entity stupid brain
|
||||
return brain;
|
||||
}
|
||||
|
||||
@@ -429,31 +502,38 @@ public class Brain<E extends LivingEntity> {
|
||||
|
||||
for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) {
|
||||
behaviorControl.doStop(level, owner, gameTime);
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ if (this.runningTasks != null) {
|
||||
+ this.runningTasks.setVisible(behaviorControl, false);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
private void startEachNonRunningBehavior(ServerLevel level, E entity) {
|
||||
- long gameTime = level.getGameTime();
|
||||
-
|
||||
- for (Map<Activity, Set<BehaviorControl<? super E>>> map : this.availableBehaviorsByPriority.values()) {
|
||||
- for (Entry<Activity, Set<BehaviorControl<? super E>>> entry : map.entrySet()) {
|
||||
- Activity activity = entry.getKey();
|
||||
- if (this.activeActivities.contains(activity)) {
|
||||
- for (BehaviorControl<? super E> behaviorControl : entry.getValue()) {
|
||||
- if (behaviorControl.getStatus() == Behavior.Status.STOPPED) {
|
||||
- behaviorControl.tryStart(level, entity, gameTime);
|
||||
- }
|
||||
- }
|
||||
+ long startTime = level.getGameTime();
|
||||
+ for (BehaviorControl<? super E> task : this.getPossibleTasks()) {
|
||||
+ if (task.getStatus() == Behavior.Status.STOPPED) {
|
||||
+ task.tryStart(level, entity, startTime);
|
||||
+ if (this.runningTasks != null && task.getStatus() == Behavior.Status.RUNNING) {
|
||||
+ this.runningTasks.setVisible(task, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
|
||||
private void tickEachRunningBehavior(ServerLevel level, E entity) {
|
||||
long gameTime = level.getGameTime();
|
||||
|
||||
for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) {
|
||||
behaviorControl.tickOrStop(level, entity, gameTime);
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ if (this.runningTasks != null && behaviorControl.getStatus() != Behavior.Status.RUNNING) {
|
||||
+ this.runningTasks.setVisible(behaviorControl, false);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/Behavior.java b/net/minecraft/world/entity/ai/behavior/Behavior.java
|
||||
index 5b0cadd2544fb2a627822e645ff32fec2e9cfda9..253b9ad671cf0932bb17d468f8b91a15a86ff77a 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/Behavior.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/Behavior.java
|
||||
@@ -14,6 +14,10 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
|
||||
private long endTimestamp;
|
||||
private final int minDuration;
|
||||
private final int maxDuration;
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ private long cachedMemoryModCount = -1;
|
||||
+ private boolean cachedHasRequiredMemoryState;
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
private final String configKey; // Paper - configurable behavior tick rate and timings
|
||||
|
||||
public Behavior(Map<MemoryModuleType<?>, MemoryStatus> entryCondition) {
|
||||
@@ -27,7 +31,7 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
|
||||
public Behavior(Map<MemoryModuleType<?>, MemoryStatus> entryCondition, int minDuration, int maxDuration) {
|
||||
this.minDuration = minDuration;
|
||||
this.maxDuration = maxDuration;
|
||||
- this.entryCondition = entryCondition;
|
||||
+ this.entryCondition = new it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap<>(entryCondition); // DivineMC - Optimize entity stupid brain - Use fastutil
|
||||
// Paper start - configurable behavior tick rate and timings
|
||||
String key = io.papermc.paper.util.MappingEnvironment.reobf() ? io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()) : this.getClass().getName();
|
||||
int lastSeparator = key.lastIndexOf('.');
|
||||
@@ -103,17 +107,26 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
- protected boolean hasRequiredMemories(E owner) {
|
||||
- for (Entry<MemoryModuleType<?>, MemoryStatus> entry : this.entryCondition.entrySet()) {
|
||||
- MemoryModuleType<?> memoryModuleType = entry.getKey();
|
||||
- MemoryStatus memoryStatus = entry.getValue();
|
||||
- if (!owner.getBrain().checkMemory(memoryModuleType, memoryStatus)) {
|
||||
- return false;
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ public boolean hasRequiredMemories(E entity) {
|
||||
+ net.minecraft.world.entity.ai.Brain<?> brain = entity.getBrain();
|
||||
+ long modCount = brain.getMemoryModCount();
|
||||
+ if (this.cachedMemoryModCount == modCount) {
|
||||
+ return this.cachedHasRequiredMemoryState;
|
||||
+ }
|
||||
+ this.cachedMemoryModCount = modCount;
|
||||
+
|
||||
+ it.unimi.dsi.fastutil.objects.ObjectIterator<it.unimi.dsi.fastutil.objects.Reference2ObjectMap.Entry<net.minecraft.world.entity.ai.memory.MemoryModuleType<?>, net.minecraft.world.entity.ai.memory.MemoryStatus>> fastIterator = ((it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap<net.minecraft.world.entity.ai.memory.MemoryModuleType<?>, net.minecraft.world.entity.ai.memory.MemoryStatus>) this.entryCondition).reference2ObjectEntrySet().fastIterator();
|
||||
+ while (fastIterator.hasNext()) {
|
||||
+ it.unimi.dsi.fastutil.objects.Reference2ObjectMap.Entry<MemoryModuleType<?>, MemoryStatus> entry = fastIterator.next();
|
||||
+ if (!brain.checkMemory(entry.getKey(), entry.getValue())) {
|
||||
+ return this.cachedHasRequiredMemoryState = false;
|
||||
}
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ return this.cachedHasRequiredMemoryState = true;
|
||||
}
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
|
||||
public static enum Status {
|
||||
STOPPED,
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java b/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java
|
||||
index ec90ea4e66c6c38d7ad41805a16c63e006e44be4..0204fe68c97d152a7c3201620b6709a8bebefdf6 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java
|
||||
@@ -120,6 +120,12 @@ public class LongJumpToRandomPos<E extends Mob> extends Behavior<E> {
|
||||
int x = blockPos.getX();
|
||||
int y = blockPos.getY();
|
||||
int z = blockPos.getZ();
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ if (this.maxLongJumpWidth < 128 && this.maxLongJumpHeight < 128) {
|
||||
+ this.jumpCandidates = org.bxteam.divinemc.util.collections.LongJumpChoiceList.forCenter(blockPos, (byte) this.maxLongJumpWidth, (byte) this.maxLongJumpHeight);
|
||||
+ return;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
this.jumpCandidates = BlockPos.betweenClosedStream(
|
||||
x - this.maxLongJumpWidth,
|
||||
y - this.maxLongJumpHeight,
|
||||
@@ -175,11 +181,27 @@ public class LongJumpToRandomPos<E extends Mob> extends Behavior<E> {
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
protected Optional<LongJumpToRandomPos.PossibleJump> getJumpCandidate(ServerLevel level) {
|
||||
- Optional<LongJumpToRandomPos.PossibleJump> randomItem = WeightedRandom.getRandomItem(level.random, this.jumpCandidates);
|
||||
- randomItem.ifPresent(this.jumpCandidates::remove);
|
||||
- return randomItem;
|
||||
+ Optional<LongJumpToRandomPos.PossibleJump> optional = getRandomFast(level.random, this.jumpCandidates);
|
||||
+ skipRemoveIfAlreadyRemoved(optional, this.jumpCandidates::remove);
|
||||
+ return optional;
|
||||
+ }
|
||||
+
|
||||
+ private Optional<LongJumpToRandomPos.PossibleJump> getRandomFast(net.minecraft.util.RandomSource random, List<LongJumpToRandomPos.PossibleJump> pool) {
|
||||
+ if (pool instanceof org.bxteam.divinemc.util.collections.LongJumpChoiceList longJumpChoiceList) {
|
||||
+ return Optional.ofNullable(longJumpChoiceList.removeRandomWeightedByDistanceSq(random));
|
||||
+ } else {
|
||||
+ return WeightedRandom.getRandomItem(random, pool);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void skipRemoveIfAlreadyRemoved(Optional<LongJumpToRandomPos.PossibleJump> result, java.util.function.Consumer<? super net.minecraft.world.entity.ai.behavior.LongJumpToRandomPos.PossibleJump> removeAction) {
|
||||
+ if (!(this.jumpCandidates instanceof org.bxteam.divinemc.util.collections.LongJumpChoiceList)) {
|
||||
+ result.ifPresent(removeAction);
|
||||
+ }
|
||||
}
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
|
||||
private boolean isAcceptableLandingPosition(ServerLevel level, E entity, BlockPos pos) {
|
||||
BlockPos blockPos = entity.blockPosition();
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java b/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java
|
||||
index 24d1928445b5571e040a2b12d5c82e77a880d9bd..dac0a23aebf2dea1972c07d5c82079da7c9837ac 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/VillagerBabiesSensor.java
|
||||
@@ -21,9 +21,22 @@ public class VillagerBabiesSensor extends Sensor<LivingEntity> {
|
||||
entity.getBrain().setMemory(MemoryModuleType.VISIBLE_VILLAGER_BABIES, this.getNearestVillagerBabies(entity));
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize baby villager sensor
|
||||
private List<LivingEntity> getNearestVillagerBabies(LivingEntity livingEntity) {
|
||||
- return ImmutableList.copyOf(this.getVisibleEntities(livingEntity).findAll(this::isVillagerBaby));
|
||||
+ NearestVisibleLivingEntities visibleEntities = this.getVisibleEntities(livingEntity);
|
||||
+ ImmutableList.Builder<LivingEntity> babies = ImmutableList.builder();
|
||||
+
|
||||
+ for (LivingEntity target : visibleEntities.nearbyEntities) {
|
||||
+ if (target.getType() == EntityType.VILLAGER
|
||||
+ && target.isBaby()
|
||||
+ && visibleEntities.lineOfSightTest.test(target)) {
|
||||
+ babies.add(target);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return babies.build();
|
||||
}
|
||||
+ // DivineMC end - Optimize baby villager sensor
|
||||
|
||||
private boolean isVillagerBaby(LivingEntity livingEntity) {
|
||||
return livingEntity.getType() == EntityType.VILLAGER && livingEntity.isBaby();
|
||||
diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
index 9b8f5d9926d68fd8b9f1f976e0be0975158cafc3..e21f024d0ed7f936ff17df16bd9666fffbf44a75 100644
|
||||
--- a/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -96,6 +96,13 @@ public class Goat extends Animal {
|
||||
this.getNavigation().setCanFloat(true);
|
||||
this.setPathfindingMalus(PathType.POWDER_SNOW, -1.0F);
|
||||
this.setPathfindingMalus(PathType.DANGER_POWDER_SNOW, -1.0F);
|
||||
+ // DivineMC start - Optimize entity stupid brain
|
||||
+ if (!this.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM)) {
|
||||
+ org.bxteam.divinemc.util.entity.SensorHelper.disableSensor(this, SensorType.NEAREST_ITEMS);
|
||||
+ } else if (net.minecraft.SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
+ throw new IllegalStateException("Goat Entity has a nearest visible wanted item memory module! This patch(Optimize-Brain, Goat.java changes) should probably be removed permanently!");
|
||||
+ }
|
||||
+ // DivineMC end - Optimize entity stupid brain
|
||||
}
|
||||
|
||||
public ItemStack createHorn() {
|
||||
@@ -1,192 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 16:57:01 +0300
|
||||
Subject: [PATCH] Optimize explosions
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
|
||||
index 6bddf42504039f2be5eb9a5a35a0835e0e3239fe..ea6da35e6c38a0b8b67d0b7a1426445eadfb540c 100644
|
||||
--- a/net/minecraft/world/level/ServerExplosion.java
|
||||
+++ b/net/minecraft/world/level/ServerExplosion.java
|
||||
@@ -375,6 +375,11 @@ public class ServerExplosion implements Explosion {
|
||||
}
|
||||
|
||||
private List<BlockPos> calculateExplodedPositions() {
|
||||
+ // DivineMC start - Optimize explosions
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableFasterTntOptimization && !level.isClientSide && !(getIndirectSourceEntity() instanceof net.minecraft.world.entity.monster.breeze.Breeze)) {
|
||||
+ return doExplosionA(this);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize explosions
|
||||
// Paper start - collision optimisations
|
||||
final ObjectArrayList<BlockPos> ret = new ObjectArrayList<>();
|
||||
|
||||
@@ -473,6 +478,157 @@ public class ServerExplosion implements Explosion {
|
||||
// Paper end - collision optimisations
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize explosions
|
||||
+ private static final it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap<org.apache.commons.lang3.tuple.Pair<net.minecraft.world.phys.Vec3, net.minecraft.world.phys.AABB>> densityCache = new it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap<>();
|
||||
+ private static final it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<net.minecraft.core.BlockPos, net.minecraft.world.level.block.state.BlockState> stateCache = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>();
|
||||
+ private static final it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<net.minecraft.core.BlockPos, net.minecraft.world.level.material.FluidState> fluidCache = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>();
|
||||
+ private static final BlockPos.MutableBlockPos posMutable = new BlockPos.MutableBlockPos(0, 0, 0);
|
||||
+ private static final it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<net.minecraft.core.BlockPos> affectedBlockPositionsSet = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>();
|
||||
+ private static boolean firstRay;
|
||||
+ private static boolean rayCalcDone;
|
||||
+
|
||||
+ public static @org.jetbrains.annotations.NotNull List<BlockPos> doExplosionA(ServerExplosion e) {
|
||||
+ List<BlockPos> toBlow;
|
||||
+
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.explosionNoBlockDamage && e.damageSource != null) {
|
||||
+ rayCalcDone = false;
|
||||
+ firstRay = true;
|
||||
+ getAffectedPositionsOnPlaneY(e, 0, 0, 15, 0, 15); // bottom
|
||||
+ getAffectedPositionsOnPlaneY(e, 15, 0, 15, 0, 15); // top
|
||||
+ getAffectedPositionsOnPlaneX(e, 0, 1, 14, 0, 15); // west
|
||||
+ getAffectedPositionsOnPlaneX(e, 15, 1, 14, 0, 15); // east
|
||||
+ getAffectedPositionsOnPlaneZ(e, 0, 1, 14, 1, 14); // north
|
||||
+ getAffectedPositionsOnPlaneZ(e, 15, 1, 14, 1, 14); // south
|
||||
+ stateCache.clear();
|
||||
+ fluidCache.clear();
|
||||
+
|
||||
+ toBlow = new ArrayList<>(affectedBlockPositionsSet);
|
||||
+ affectedBlockPositionsSet.clear();
|
||||
+ } else {
|
||||
+ toBlow = java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ densityCache.clear();
|
||||
+
|
||||
+ return toBlow;
|
||||
+ }
|
||||
+
|
||||
+ private static void getAffectedPositionsOnPlaneX(Explosion e, int x, int yStart, int yEnd, int zStart, int zEnd) {
|
||||
+ if (!rayCalcDone) {
|
||||
+ final double xRel = (double) x / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ for (int z = zStart; z <= zEnd; ++z) {
|
||||
+ double zRel = (double) z / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ for (int y = yStart; y <= yEnd; ++y) {
|
||||
+ double yRel = (double) y / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ if (checkAffectedPosition((ServerExplosion) e, xRel, yRel, zRel)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void getAffectedPositionsOnPlaneY(Explosion e, int y, int xStart, int xEnd, int zStart, int zEnd) {
|
||||
+ if (!rayCalcDone) {
|
||||
+ final double yRel = (double) y / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ for (int z = zStart; z <= zEnd; ++z) {
|
||||
+ double zRel = (double) z / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ for (int x = xStart; x <= xEnd; ++x) {
|
||||
+ double xRel = (double) x / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ if (checkAffectedPosition((ServerExplosion) e, xRel, yRel, zRel)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void getAffectedPositionsOnPlaneZ(Explosion e, int z, int xStart, int xEnd, int yStart, int yEnd) {
|
||||
+ if (!rayCalcDone) {
|
||||
+ final double zRel = (double) z / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ for (int x = xStart; x <= xEnd; ++x) {
|
||||
+ double xRel = (double) x / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ for (int y = yStart; y <= yEnd; ++y) {
|
||||
+ double yRel = (double) y / 15.0D * 2.0D - 1.0D;
|
||||
+
|
||||
+ if (checkAffectedPosition((ServerExplosion) e, xRel, yRel, zRel)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static boolean checkAffectedPosition(ServerExplosion e, double xRel, double yRel, double zRel) {
|
||||
+ double len = Math.sqrt(xRel * xRel + yRel * yRel + zRel * zRel);
|
||||
+ double xInc = (xRel / len) * 0.3;
|
||||
+ double yInc = (yRel / len) * 0.3;
|
||||
+ double zInc = (zRel / len) * 0.3;
|
||||
+ float rand = e.level().random.nextFloat();
|
||||
+ float sizeRand = (org.bxteam.divinemc.DivineConfig.tntRandomRange >= 0 ? (float) org.bxteam.divinemc.DivineConfig.tntRandomRange : rand);
|
||||
+ float size = e.radius() * (0.7F + sizeRand * 0.6F);
|
||||
+ Vec3 vec3 = e.center();
|
||||
+ double posX = vec3.x;
|
||||
+ double posY = vec3.y;
|
||||
+ double posZ = vec3.z;
|
||||
+
|
||||
+ for (float f1 = 0.3F; size > 0.0F; size -= 0.22500001F) {
|
||||
+ posMutable.set(posX, posY, posZ);
|
||||
+
|
||||
+ // Don't query already cached positions again from the world
|
||||
+ BlockState state = stateCache.get(posMutable);
|
||||
+ FluidState fluid = fluidCache.get(posMutable);
|
||||
+ BlockPos posImmutable = null;
|
||||
+
|
||||
+ if (state == null) {
|
||||
+ posImmutable = posMutable.immutable();
|
||||
+ state = e.level().getBlockState(posImmutable);
|
||||
+ stateCache.put(posImmutable, state);
|
||||
+ fluid = e.level().getFluidState(posImmutable);
|
||||
+ fluidCache.put(posImmutable, fluid);
|
||||
+ }
|
||||
+
|
||||
+ if (!state.isAir()) {
|
||||
+ float resistance = Math.max(state.getBlock().getExplosionResistance(), fluid.getExplosionResistance());
|
||||
+
|
||||
+ if (e.source != null) {
|
||||
+ resistance = e.source.getBlockExplosionResistance(e, e.level(), posMutable, state, fluid, resistance);
|
||||
+ }
|
||||
+
|
||||
+ size -= (resistance + 0.3F) * 0.3F;
|
||||
+ }
|
||||
+
|
||||
+ if (size > 0.0F) {
|
||||
+ if ((e.source == null || e.source.shouldBlockExplode(e, e.level(), posMutable, state, size)))
|
||||
+ affectedBlockPositionsSet.add(posImmutable != null ? posImmutable : posMutable.immutable());
|
||||
+ } else if (firstRay) {
|
||||
+ rayCalcDone = true;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ firstRay = false;
|
||||
+
|
||||
+ posX += xInc;
|
||||
+ posY += yInc;
|
||||
+ posZ += zInc;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ private Optional<Float> noBlockCalcsWithNoBLockDamage(final ExplosionDamageCalculator instance, final Explosion explosion, final BlockGetter blockGetter, final BlockPos blockPos, final BlockState blockState, final FluidState fluidState) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.explosionNoBlockDamage) return Optional.of(Blocks.BEDROCK.getExplosionResistance());
|
||||
+ return instance.getBlockExplosionResistance(explosion, blockGetter, blockPos, blockState, fluidState);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize explosions
|
||||
+
|
||||
private void hurtEntities() {
|
||||
float f = this.radius * 2.0F;
|
||||
int floor = Mth.floor(this.center.x - f - 1.0);
|
||||
@@ -565,6 +721,11 @@ public class ServerExplosion implements Explosion {
|
||||
}
|
||||
|
||||
private void interactWithBlocks(List<BlockPos> blocks) {
|
||||
+ // DivineMC start - Optimize explosions
|
||||
+ if (org.bxteam.divinemc.DivineConfig.explosionNoBlockDamage) {
|
||||
+ blocks.clear();
|
||||
+ }
|
||||
+ // DivineMC end - Optimize explosions
|
||||
List<ServerExplosion.StackCollector> list = new ArrayList<>();
|
||||
Util.shuffle(blocks, this.level.random);
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 18:03:13 +0300
|
||||
Subject: [PATCH] Option to allow weird movement and disable teleporting
|
||||
players when they move too quickly
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index f8c76bb2c9fa625e191036dc58ef3dfb1d4ee930..5b8031a45b1f4f6d0e86c2a839d173a6e3f4f697 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -574,7 +574,7 @@ public class ServerGamePacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// Paper end - Prevent moving into unloaded chunks
|
||||
- if (d7 - d6 > Math.max(100.0, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.alwaysAllowWeirdMovement && (d7 - d6 > Math.max(100.0, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner())) { // DivineMC - stop weird movement
|
||||
// CraftBukkit end
|
||||
LOGGER.warn(
|
||||
"{} (vehicle of {}) moved too quickly! {},{},{}", rootVehicle.getName().getString(), this.player.getName().getString(), d3, d4, d5
|
||||
@@ -604,7 +604,7 @@ public class ServerGamePacketListenerImpl
|
||||
d5 = d2 - rootVehicle.getZ();
|
||||
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||
boolean flag2 = false;
|
||||
- if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.alwaysAllowWeirdMovement && (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold)) { // Spigot // DivineMC - stop weird movement
|
||||
flag2 = true; // Paper - diff on change, this should be moved wrongly
|
||||
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
|
||||
}
|
||||
@@ -1453,18 +1453,22 @@ public class ServerGamePacketListenerImpl
|
||||
if (this.shouldCheckPlayerMovement(isFallFlying)) {
|
||||
float f2 = isFallFlying ? 300.0F : 100.0F;
|
||||
if (d7 - d6 > Math.max(f2, Mth.square(org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed))) {
|
||||
- // CraftBukkit end
|
||||
- // Paper start - Add fail move event
|
||||
- io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
|
||||
- toX, toY, toZ, toYaw, toPitch, true);
|
||||
- if (!event.isAllowed()) {
|
||||
- if (event.getLogWarning()) {
|
||||
- LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5);
|
||||
+ // DivineMC start - Stop teleporting players when they move too quickly
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.alwaysAllowWeirdMovement && !(org.bxteam.divinemc.DivineConfig.ignoreMovedTooQuicklyWhenLagging && player.serverLevel().getServer().lagging)) {
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - Add fail move event
|
||||
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
|
||||
+ toX, toY, toZ, toYaw, toPitch, true);
|
||||
+ if (!event.isAllowed()) {
|
||||
+ if (event.getLogWarning()) {
|
||||
+ LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getName().getString(), d3, d4, d5);
|
||||
+ }
|
||||
+ this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
|
||||
+ return;
|
||||
}
|
||||
- this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
|
||||
- return;
|
||||
+ // Paper end - Add fail move event
|
||||
}
|
||||
- // Paper end - Add fail move event
|
||||
+ // DivineMC end - Stop teleporting players when they move too quickly
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1525,6 +1529,7 @@ public class ServerGamePacketListenerImpl
|
||||
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||
boolean movedWrongly = false; // Paper - Add fail move event; rename
|
||||
if (!this.player.isChangingDimension()
|
||||
+ && !org.bxteam.divinemc.DivineConfig.alwaysAllowWeirdMovement // DivineMC - Stop teleporting players when they move too quickly
|
||||
&& d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold // Spigot
|
||||
&& !this.player.isSleeping()
|
||||
&& !this.player.gameMode.isCreative()
|
||||
@@ -1,331 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 18:38:26 +0300
|
||||
Subject: [PATCH] Lag compensation
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 5a726da8535aa939f043829a3c60fdd9d4ed154a..0aebdd1cb0e1b63ff9a867bdcda7cbdc3c194b56 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -289,6 +289,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation
|
||||
protected boolean upnp = false; // Purpur - UPnP Port Forwarding
|
||||
public java.util.concurrent.Semaphore serverLevelTickingSemaphore = null; // DivineMC - Parallel world ticking
|
||||
+ public final org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag compensation
|
||||
|
||||
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
||||
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
||||
@@ -1558,6 +1559,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
|
||||
this.server.spark.tickStart(); // Paper - spark
|
||||
+ this.tpsCalculator.doTick(); // DivineMC - Lag compenstation
|
||||
new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper - Server Tick Events
|
||||
this.tickCount++;
|
||||
this.tickRateManager.tick();
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index a70007d324e2169d1b2a1a11046500196b8b5660..53b606c34f65b80a676ddd26d64028dbdebecb43 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -218,6 +218,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
||||
private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
|
||||
public boolean hasRidableMoveEvent = false; // Purpur - Ridables
|
||||
+ public org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag Compensation
|
||||
|
||||
public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
||||
@@ -774,6 +775,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
}
|
||||
|
||||
+ this.tpsCalculator.doTick(); // DivineMC - Lag compensation
|
||||
+
|
||||
this.updateSkyBrightness();
|
||||
if (runsNormally) {
|
||||
this.tickTime();
|
||||
@@ -853,11 +856,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
this.setDayTime(this.preciseTime);
|
||||
} else
|
||||
// Purpur end - Configurable daylight cycle
|
||||
- this.setDayTime(this.levelData.getDayTime() + 1L);
|
||||
+ this.setDayTime(lagCompensation(this.levelData.getDayTime()) + 1L); // DivineMC - Lag compensation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private long lagCompensation(long original) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.timeAcceleration) return original;
|
||||
+ return original + this.tpsCalculator.applicableMissedTicks();
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
public void setDayTime(long time) {
|
||||
this.serverLevelData.setDayTime(time);
|
||||
// Purpur start - Configurable daylight cycle
|
||||
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
|
||||
index 04a1c17a34b495b71eb1b0ccd597cef83480464d..edb128a3f454e7b3009ca360509decd7a618de5d 100644
|
||||
--- a/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -555,6 +555,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
}
|
||||
|
||||
+ lagCompensation(); // DivineMC - Lag Compensation
|
||||
this.tickEffects();
|
||||
this.animStepO = this.animStep;
|
||||
this.yBodyRotO = this.yBodyRot;
|
||||
@@ -563,6 +564,17 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
this.xRotO = this.getXRot();
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag Compensation
|
||||
+ private void lagCompensation() {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.potionEffectAcceleration) return;
|
||||
+ if (this.level().isClientSide()) return;
|
||||
+
|
||||
+ for (int i = 0; i < ((ServerLevel) this.level()).tpsCalculator.applicableMissedTicks(); i++) {
|
||||
+ tickEffects();
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Lag Compensation
|
||||
+
|
||||
@Override
|
||||
protected float getBlockSpeedFactor() {
|
||||
return Mth.lerp((float)this.getAttributeValue(Attributes.MOVEMENT_EFFICIENCY), super.getBlockSpeedFactor(), 1.0F);
|
||||
diff --git a/net/minecraft/world/entity/PortalProcessor.java b/net/minecraft/world/entity/PortalProcessor.java
|
||||
index be357d9e3c5327ceec12c31830551a564c8cea1b..f77da420bc88df6ec304086fc1eba0690fe278b1 100644
|
||||
--- a/net/minecraft/world/entity/PortalProcessor.java
|
||||
+++ b/net/minecraft/world/entity/PortalProcessor.java
|
||||
@@ -26,10 +26,20 @@ public class PortalProcessor {
|
||||
return false;
|
||||
} else {
|
||||
this.insidePortalThisTick = false;
|
||||
- return canChangeDimensions && this.portalTime++ >= this.portal.getPortalTransitionTime(level, entity);
|
||||
+ return canChangeDimensions && lagCompensation(this.portalTime++, level) >= this.portal.getPortalTransitionTime(level, entity); // DivineMC - Lag compensation
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private int lagCompensation(int original, ServerLevel world) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.portalAcceleration) return original;
|
||||
+ if (world.isClientSide()) return original;
|
||||
+
|
||||
+ portalTime = portalTime + world.tpsCalculator.applicableMissedTicks();
|
||||
+ return portalTime;
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
@Nullable
|
||||
public TeleportTransition getPortalDestination(ServerLevel level, Entity entity) {
|
||||
return this.portal.getPortalDestination(level, entity, this.entryPosition);
|
||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 771b169fa360411bb313ae04c7dd55836875c611..e64ed6a23efbe89b8d3dd1e5a2a69ba4b7743369 100644
|
||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -153,8 +153,25 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
}
|
||||
// Paper end - EAR 2
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private void lagCompensation() {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.pickupAcceleration) return;
|
||||
+ if ((this).level().isClientSide()) return;
|
||||
+
|
||||
+ if (pickupDelay == 0) return;
|
||||
+
|
||||
+ if (pickupDelay - ((ServerLevel) this.level()).tpsCalculator.applicableMissedTicks() <= 0) {
|
||||
+ pickupDelay = 0;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pickupDelay = pickupDelay - ((ServerLevel) this.level()).tpsCalculator.applicableMissedTicks();
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
@Override
|
||||
public void tick() {
|
||||
+ lagCompensation(); // DivineMC - Lag compensation
|
||||
if (this.getItem().isEmpty()) {
|
||||
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/item/Item.java b/net/minecraft/world/item/Item.java
|
||||
index 6821d39a24ef610ea8b04f6dbeca2cdc0b8e7787..a4d76e4aafb98b1bbc0e5a80d65cf0f9a3a53fd5 100644
|
||||
--- a/net/minecraft/world/item/Item.java
|
||||
+++ b/net/minecraft/world/item/Item.java
|
||||
@@ -258,9 +258,21 @@ public class Item implements FeatureElement, ItemLike {
|
||||
return consumable != null ? consumable.animation() : ItemUseAnimation.NONE;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private int lagCompensation(int original, net.minecraft.server.level.ServerLevel level) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.eatingAcceleration || original == 0) return original;
|
||||
+ return org.bxteam.divinemc.util.tps.TPSUtil.tt20(original, true, level);
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
public int getUseDuration(ItemStack stack, LivingEntity entity) {
|
||||
Consumable consumable = stack.get(DataComponents.CONSUMABLE);
|
||||
- return consumable != null ? consumable.consumeTicks() : 0;
|
||||
+ int original = consumable != null ? consumable.consumeTicks() : 0;
|
||||
+ if (entity.level() instanceof net.minecraft.server.level.ServerLevel serverLevel) {
|
||||
+ return lagCompensation(original, serverLevel);
|
||||
+ }
|
||||
+
|
||||
+ return original;
|
||||
}
|
||||
|
||||
public boolean releaseUsing(ItemStack stack, Level level, LivingEntity entity, int timeLeft) {
|
||||
diff --git a/net/minecraft/world/level/GameRules.java b/net/minecraft/world/level/GameRules.java
|
||||
index 02d64a5ea756b2c91a71b7a0fc0f21219983616a..d515ba4e775e1199e1cbf4f79978d318eaa6b336 100644
|
||||
--- a/net/minecraft/world/level/GameRules.java
|
||||
+++ b/net/minecraft/world/level/GameRules.java
|
||||
@@ -320,8 +320,31 @@ public class GameRules {
|
||||
}
|
||||
|
||||
public int getInt(GameRules.Key<GameRules.IntegerValue> key) {
|
||||
- return this.getRule(key).get();
|
||||
+ return lagCompensation(this.getRule(key).get(), key); // DivineMC - Lag compensation
|
||||
+ }
|
||||
+
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private final java.util.concurrent.atomic.AtomicReference<net.minecraft.server.level.ServerLevel> level = new java.util.concurrent.atomic.AtomicReference<>();
|
||||
+
|
||||
+ private int lagCompensation(int original, GameRules.Key<GameRules.IntegerValue> rule) {
|
||||
+ ServerLevel level = getOrCacheLevel();
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.randomTickSpeedAcceleration) return original;
|
||||
+ if (!(rule == GameRules.RULE_RANDOMTICKING)) return original;
|
||||
+ return (int) (original * org.bxteam.divinemc.util.tps.TPSCalculator.MAX_TPS / (float) level.tpsCalculator.getMostAccurateTPS());
|
||||
+ }
|
||||
+
|
||||
+ private ServerLevel getOrCacheLevel() {
|
||||
+ if (level.get() == null) {
|
||||
+ for (final ServerLevel level : MinecraftServer.getServer().getAllLevels()) {
|
||||
+ if (level.getGameRules() == this) {
|
||||
+ this.level.set(level);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return level.get();
|
||||
}
|
||||
+ // DivineMC end - Lag compensation
|
||||
|
||||
public static class BooleanValue extends GameRules.Value<GameRules.BooleanValue> {
|
||||
private boolean value;
|
||||
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index b631e35e965b1914cdeeddab8bd6bdbfd2465079..bb7dab597850fba8f0dff4461fc518e0a33b00c7 100644
|
||||
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -346,13 +346,21 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private float lagCompensation(float original, Player player) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.blockBreakingAcceleration) return original;
|
||||
+ if (player.level().isClientSide) return original;
|
||||
+ return original * org.bxteam.divinemc.util.tps.TPSCalculator.MAX_TPS / (float) ((ServerLevel) player.level()).tpsCalculator.getMostAccurateTPS();
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
protected float getDestroyProgress(BlockState state, Player player, BlockGetter level, BlockPos pos) {
|
||||
float destroySpeed = state.getDestroySpeed(level, pos);
|
||||
if (destroySpeed == -1.0F) {
|
||||
- return 0.0F;
|
||||
+ return lagCompensation(0.0F, player); // DivineMC - Lag compensation
|
||||
} else {
|
||||
int i = player.hasCorrectToolForDrops(state) ? 30 : 100;
|
||||
- return player.getDestroySpeed(state) / destroySpeed / i;
|
||||
+ return lagCompensation(player.getDestroySpeed(state) / destroySpeed / i, player); // DivineMC - Lag compensation
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index b245f594ff91e2d29c83f56b9ed5165f37387e7e..534384727e852dc8ea822f49f182af49eb3a40c1 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -907,6 +907,19 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
this.ticker = ticker;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private <T extends BlockEntity> void lagCompensation(Runnable original) {
|
||||
+ original.run();
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled) return;
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.blockEntityAcceleration) return;
|
||||
+ if (LevelChunk.this.level.isClientSide()) return;
|
||||
+
|
||||
+ for (int i = 0; i < ((ServerLevel) this.blockEntity.getLevel()).tpsCalculator.applicableMissedTicks(); i++) {
|
||||
+ original.run();
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
@Override
|
||||
public void tick() {
|
||||
if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) {
|
||||
@@ -915,7 +928,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
try {
|
||||
BlockState blockState = LevelChunk.this.getBlockState(blockPos);
|
||||
if (this.blockEntity.getType().isValid(blockState)) {
|
||||
- this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockState, this.blockEntity);
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ lagCompensation(() -> {
|
||||
+ this.ticker.tick(LevelChunk.this.level, this.blockEntity.getBlockPos(), blockState, this.blockEntity);
|
||||
+ });
|
||||
+ // DivineMC end - Lag compensation
|
||||
this.loggedInvalidBlockState = false;
|
||||
// Paper start - Remove the Block Entity if it's invalid
|
||||
} else {
|
||||
diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java
|
||||
index 35b5a33c79c883f28c99c992695b188524593b55..6845a1c3b6038700751312d8beb0f9a2844003a5 100644
|
||||
--- a/net/minecraft/world/level/material/LavaFluid.java
|
||||
+++ b/net/minecraft/world/level/material/LavaFluid.java
|
||||
@@ -175,9 +175,22 @@ public abstract class LavaFluid extends FlowingFluid {
|
||||
return fluidState.getHeight(blockReader, pos) >= 0.44444445F && fluid.is(FluidTags.WATER);
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private int lagCompensation(int original, ServerLevel level) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.fluidAcceleration) return original;
|
||||
+ return org.bxteam.divinemc.util.tps.TPSUtil.tt20(original, true, level);
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
@Override
|
||||
public int getTickDelay(LevelReader level) {
|
||||
- return level.dimensionType().ultraWarm() ? level.getWorldBorder().world.purpurConfig.lavaSpeedNether : level.getWorldBorder().world.purpurConfig.lavaSpeedNotNether; // Purpur - Make lava flow speed configurable
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ int original = level.dimensionType().ultraWarm() ? level.getWorldBorder().world.purpurConfig.lavaSpeedNether : level.getWorldBorder().world.purpurConfig.lavaSpeedNotNether; // Purpur - Make lava flow speed configurable
|
||||
+ if (level instanceof ServerLevel serverLevel) {
|
||||
+ return lagCompensation(original, serverLevel);
|
||||
+ }
|
||||
+ return original;
|
||||
+ // DivineMC end - Lag compensation
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/level/material/WaterFluid.java b/net/minecraft/world/level/material/WaterFluid.java
|
||||
index 2e4fed7c27910b6c886f710f33b0841c2a175837..89f22ebcbaf21df3afb6a00f60d8e00777875aac 100644
|
||||
--- a/net/minecraft/world/level/material/WaterFluid.java
|
||||
+++ b/net/minecraft/world/level/material/WaterFluid.java
|
||||
@@ -113,8 +113,16 @@ public abstract class WaterFluid extends FlowingFluid {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Lag compensation
|
||||
+ private int lagCompensation(ServerLevel level) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.lagCompensationEnabled || !org.bxteam.divinemc.DivineConfig.fluidAcceleration) return 5;
|
||||
+ return org.bxteam.divinemc.util.tps.TPSUtil.tt20(5, true, level);
|
||||
+ }
|
||||
+ // DivineMC end - Lag compensation
|
||||
+
|
||||
@Override
|
||||
public int getTickDelay(LevelReader level) {
|
||||
+ if (level instanceof ServerLevel serverLevel) return lagCompensation(serverLevel); // DivineMC - Lag compensation
|
||||
return 5;
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:14:09 +0300
|
||||
Subject: [PATCH] Skip EntityScheduler's executeTick checks if there isn't any
|
||||
tasks to be run
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index df07a4a62bd518f3a13995a3ccc7970c714bad7b..851f943cddad03ae12e1ed85f64072682447a367 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -290,6 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
protected boolean upnp = false; // Purpur - UPnP Port Forwarding
|
||||
public java.util.concurrent.Semaphore serverLevelTickingSemaphore = null; // DivineMC - Parallel world ticking
|
||||
public final org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag compensation
|
||||
+ public final Set<net.minecraft.world.entity.Entity> entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // DivineMC - Skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
|
||||
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
||||
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
||||
@@ -1706,17 +1707,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
||||
// Paper start - Folia scheduler API
|
||||
((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick();
|
||||
- getAllLevels().forEach(level -> {
|
||||
- for (final net.minecraft.world.entity.Entity entity : level.getEntities().getAll()) {
|
||||
- if (entity.isRemoved()) {
|
||||
- continue;
|
||||
- }
|
||||
- final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();
|
||||
- if (bukkit != null) {
|
||||
- bukkit.taskScheduler.executeTick();
|
||||
- }
|
||||
+ // DivineMC start - Skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
+ for (final net.minecraft.world.entity.Entity entity : entitiesWithScheduledTasks) {
|
||||
+ if (entity.isRemoved()) {
|
||||
+ continue;
|
||||
}
|
||||
- });
|
||||
+
|
||||
+ final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();
|
||||
+ if (bukkit != null) {
|
||||
+ bukkit.taskScheduler.executeTick();
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
// Paper end - Folia scheduler API
|
||||
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper
|
||||
this.getFunctions().tick();
|
||||
@@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:17:31 +0300
|
||||
Subject: [PATCH] Carpet-Fixes: RecipeManager Optimize
|
||||
|
||||
Original project: https://github.com/fxmorin/carpet-fixes
|
||||
Optimized the RecipeManager getFirstMatch call to be up to 3x faster
|
||||
This is a fully vanilla optimization. Improves: [Blast]Furnace/Campfire/Smoker/Stonecutter/Crafting/Sheep Color Choosing
|
||||
This was mostly made for the auto crafting table, since the performance boost is much more visible while using that mod
|
||||
|
||||
diff --git a/net/minecraft/world/item/crafting/RecipeManager.java b/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
index c7d91a38fc3b5cf2487e09719a1f9bc39ca5d20e..875e9711c9dacaf73636c7c7ce1cf740a23f006f 100644
|
||||
--- a/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
+++ b/net/minecraft/world/item/crafting/RecipeManager.java
|
||||
@@ -166,7 +166,7 @@ public class RecipeManager extends SimplePreparableReloadListener<RecipeMap> imp
|
||||
|
||||
public <I extends RecipeInput, T extends Recipe<I>> Optional<RecipeHolder<T>> getRecipeFor(RecipeType<T> recipeType, I input, Level level) {
|
||||
// CraftBukkit start
|
||||
- List<RecipeHolder<T>> list = this.recipes.getRecipesFor(recipeType, input, level).toList();
|
||||
+ List<RecipeHolder<T>> list = this.recipes.getRecipesForList(recipeType, input, level); // DivineMC - Carpet-Fixes - Remove streams to be faster
|
||||
return (list.isEmpty()) ? Optional.empty() : Optional.of(list.getLast()); // CraftBukkit - SPIGOT-4638: last recipe gets priority
|
||||
// CraftBukkit end
|
||||
}
|
||||
diff --git a/net/minecraft/world/item/crafting/RecipeMap.java b/net/minecraft/world/item/crafting/RecipeMap.java
|
||||
index 098753ddd215b6ef5915fac71d8c4f0b19cf4142..1778e58dca9430756d59d07bf017ebe4cc1f4ed4 100644
|
||||
--- a/net/minecraft/world/item/crafting/RecipeMap.java
|
||||
+++ b/net/minecraft/world/item/crafting/RecipeMap.java
|
||||
@@ -75,4 +75,24 @@ public class RecipeMap {
|
||||
public <I extends RecipeInput, T extends Recipe<I>> Stream<RecipeHolder<T>> getRecipesFor(RecipeType<T> type, I input, Level level) {
|
||||
return input.isEmpty() ? Stream.empty() : this.byType(type).stream().filter(recipeHolder -> recipeHolder.value().matches(input, level));
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Carpet-Fixes - Remove streams to be faster
|
||||
+ public <I extends RecipeInput, T extends Recipe<I>> java.util.List<RecipeHolder<T>> getRecipesForList(RecipeType<T> type, I input, Level world) {
|
||||
+ java.util.List<RecipeHolder<T>> list;
|
||||
+
|
||||
+ if (input.isEmpty()) {
|
||||
+ return java.util.List.of();
|
||||
+ } else {
|
||||
+ list = new java.util.ArrayList<>();
|
||||
+ }
|
||||
+
|
||||
+ for (RecipeHolder<T> recipeholder : this.byType(type)) {
|
||||
+ if (recipeholder.value().matches(input, world)) {
|
||||
+ list.add(recipeholder);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return list;
|
||||
+ }
|
||||
+ // DivineMC end - Carpet-Fixes - Remove streams to be faster
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:24:47 +0300
|
||||
Subject: [PATCH] Snowball and Egg knockback
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/projectile/Snowball.java b/net/minecraft/world/entity/projectile/Snowball.java
|
||||
index 1d399532c67c213c95c06837b0c7855384f1a25c..cad1f8cb68ef9615587e651a3120f68a3c32add0 100644
|
||||
--- a/net/minecraft/world/entity/projectile/Snowball.java
|
||||
+++ b/net/minecraft/world/entity/projectile/Snowball.java
|
||||
@@ -54,6 +54,12 @@ public class Snowball extends ThrowableItemProjectile {
|
||||
Entity entity = result.getEntity();
|
||||
int i = entity.level().purpurConfig.snowballDamage >= 0 ? entity.level().purpurConfig.snowballDamage : entity instanceof Blaze ? 3 : 0; // Purpur - Add configurable snowball damage
|
||||
entity.hurt(this.damageSources().thrown(this, this.getOwner()), i);
|
||||
+ // DivineMC start - Make snowball can knockback player
|
||||
+ if (this.level().divineConfig.snowballCanKnockback && entity instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ entity.hurt(this.damageSources().thrown(this, this.getOwner()), 0.0000001F);
|
||||
+ serverPlayer.knockback(0.4000000059604645D, this.getX() - entity.getX(), this.getZ() - entity.getZ());
|
||||
+ }
|
||||
+ // DivineMC end - Make snowball can knockback player
|
||||
}
|
||||
|
||||
// Purpur start - options to extinguish fire blocks with snowballs - borrowed and modified code from ThrownPotion#onHitBlock and ThrownPotion#dowseFire
|
||||
diff --git a/net/minecraft/world/entity/projectile/ThrownEgg.java b/net/minecraft/world/entity/projectile/ThrownEgg.java
|
||||
index 76481c0e77fc3a2e4be8eeb9de8d1e6de5507c64..8f0aa83cc81f36d70a39600a82d0212db70e02ec 100644
|
||||
--- a/net/minecraft/world/entity/projectile/ThrownEgg.java
|
||||
+++ b/net/minecraft/world/entity/projectile/ThrownEgg.java
|
||||
@@ -52,7 +52,14 @@ public class ThrownEgg extends ThrowableItemProjectile {
|
||||
@Override
|
||||
protected void onHitEntity(EntityHitResult result) {
|
||||
super.onHitEntity(result);
|
||||
+ net.minecraft.world.entity.Entity entity = result.getEntity(); // DivineMC - make egg can knockback player
|
||||
result.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F);
|
||||
+ // DivineMC start - Make egg can knockback player
|
||||
+ if (this.level().divineConfig.eggCanKnockback && entity instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ entity.hurt(this.damageSources().thrown(this, this.getOwner()), 0.0000001F);
|
||||
+ serverPlayer.knockback(0.4000000059604645D, this.getX() - entity.getX(), this.getZ() - entity.getZ());
|
||||
+ }
|
||||
+ // DivineMC end - Make egg can knockback player
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,34 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:28:34 +0300
|
||||
Subject: [PATCH] Block Log4Shell exploit
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 5b8031a45b1f4f6d0e86c2a839d173a6e3f4f697..a3ec8c92dae7735bb0b1ececc9851c829c486a53 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2425,6 +2425,7 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
private void tryHandleChat(String message, Runnable handler, boolean sync) { // CraftBukkit
|
||||
+ if (ServerGamePacketListenerImpl.isLog4ShellExploit(message)) return; // DivineMC - Block Log4Shell exploit
|
||||
if (isChatMessageIllegal(message)) {
|
||||
this.disconnectAsync(Component.translatable("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper - add proper async disconnect
|
||||
} else if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales
|
||||
@@ -2453,6 +2454,15 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Block Log4Shell exploit
|
||||
+ public static boolean isLog4ShellExploit(String message) {
|
||||
+ java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(".*\\$\\{[^}]*}.*");
|
||||
+ java.util.regex.Matcher matcher = pattern.matcher(message);
|
||||
+
|
||||
+ return matcher.find();
|
||||
+ }
|
||||
+ // DivineMC end - Block Log4Shell exploit
|
||||
+
|
||||
public static boolean isChatMessageIllegal(String message) {
|
||||
for (int i = 0; i < message.length(); i++) {
|
||||
if (!StringUtil.isAllowedChatCharacter(message.charAt(i))) {
|
||||
@@ -1,44 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:43:42 +0300
|
||||
Subject: [PATCH] Re-Fix MC-117075
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||
index 9608aa7231e1e19ac34f7fcf6cc4051da01f2f3e..92fc936c6bdbda909b9cdf157ec9d46a4872098c 100644
|
||||
--- a/net/minecraft/world/level/Level.java
|
||||
+++ b/net/minecraft/world/level/Level.java
|
||||
@@ -113,7 +113,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
public static final int TICKS_PER_DAY = 24000;
|
||||
public static final int MAX_ENTITY_SPAWN_Y = 20000000;
|
||||
public static final int MIN_ENTITY_SPAWN_Y = -20000000;
|
||||
- public final List<TickingBlockEntity> blockEntityTickers = Lists.newArrayList(); // Paper - public
|
||||
+ public final org.bxteam.divinemc.util.BlockEntityTickersList blockEntityTickers = new org.bxteam.divinemc.util.BlockEntityTickersList(); // Paper - public // DivineMC - optimize block entity removals - Fix MC-117075
|
||||
protected final NeighborUpdater neighborUpdater;
|
||||
private final List<TickingBlockEntity> pendingBlockEntityTickers = Lists.newArrayList();
|
||||
private boolean tickingBlockEntities;
|
||||
@@ -1521,14 +1521,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
boolean runsNormally = this.tickRateManager().runsNormally();
|
||||
|
||||
int tickedEntities = 0; // Paper - rewrite chunk system
|
||||
- var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<TickingBlockEntity>(); // Paper - Fix MC-117075; use removeAll
|
||||
- toRemove.add(null); // Paper - Fix MC-117075
|
||||
for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters
|
||||
this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0;
|
||||
TickingBlockEntity tickingBlockEntity = this.blockEntityTickers.get(this.tileTickPosition);
|
||||
// Spigot end
|
||||
if (tickingBlockEntity.isRemoved()) {
|
||||
- toRemove.add(tickingBlockEntity); // Paper - Fix MC-117075; use removeAll
|
||||
+ this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // DivineMC - optimize block entity removals - Fix MC-117075
|
||||
} else if (runsNormally && this.shouldTickBlocksAt(tickingBlockEntity.getPos())) {
|
||||
tickingBlockEntity.tick();
|
||||
// DivineMC start - Parallel world ticking
|
||||
@@ -1539,7 +1537,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
|
||||
// DivineMC end - Parallel world ticking
|
||||
}
|
||||
}
|
||||
- this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075
|
||||
+ this.blockEntityTickers.removeMarkedEntries(); // DivineMC - optimize block entity removals - Fix MC-117075
|
||||
|
||||
this.tickingBlockEntities = false;
|
||||
this.spigotConfig.currentPrimedTnt = 0; // Spigot
|
||||
@@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:50:02 +0300
|
||||
Subject: [PATCH] Skip distanceToSqr call in ServerEntity#sendChanges if the
|
||||
delta movement hasn't changed
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
|
||||
index b6053158f5d9b6ad325ea075ab7c60f9966ba496..c7ad6bf5dd8cb8a27de3e3ed82c6eefaa36c5c08 100644
|
||||
--- a/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -203,23 +203,27 @@ public class ServerEntity {
|
||||
|
||||
if (this.entity.hasImpulse || this.trackDelta || this.entity instanceof LivingEntity && ((LivingEntity)this.entity).isFallFlying()) {
|
||||
Vec3 deltaMovement = this.entity.getDeltaMovement();
|
||||
- double d = deltaMovement.distanceToSqr(this.lastSentMovement);
|
||||
- if (d > 1.0E-7 || d > 0.0 && deltaMovement.lengthSqr() == 0.0) {
|
||||
- this.lastSentMovement = deltaMovement;
|
||||
- if (this.entity instanceof AbstractHurtingProjectile abstractHurtingProjectile) {
|
||||
- this.broadcast
|
||||
- .accept(
|
||||
- new ClientboundBundlePacket(
|
||||
- List.of(
|
||||
- new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement),
|
||||
- new ClientboundProjectilePowerPacket(abstractHurtingProjectile.getId(), abstractHurtingProjectile.accelerationPower)
|
||||
+ // DivineMC start - Skip "distanceToSqr" call in "ServerEntity#sendChanges" if the delta movement hasn't changed
|
||||
+ if (deltaMovement != this.lastSentMovement) {
|
||||
+ double d = deltaMovement.distanceToSqr(this.lastSentMovement);
|
||||
+ if (d > 1.0E-7 || d > 0.0 && deltaMovement.lengthSqr() == 0.0) {
|
||||
+ this.lastSentMovement = deltaMovement;
|
||||
+ if (this.entity instanceof AbstractHurtingProjectile abstractHurtingProjectile) {
|
||||
+ this.broadcast
|
||||
+ .accept(
|
||||
+ new ClientboundBundlePacket(
|
||||
+ List.of(
|
||||
+ new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement),
|
||||
+ new ClientboundProjectilePowerPacket(abstractHurtingProjectile.getId(), abstractHurtingProjectile.accelerationPower)
|
||||
+ )
|
||||
)
|
||||
- )
|
||||
- );
|
||||
- } else {
|
||||
- this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement));
|
||||
+ );
|
||||
+ } else {
|
||||
+ this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement));
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ // DivineMC end - Skip "distanceToSqr" call in "ServerEntity#sendChanges" if the delta movement hasn't changed
|
||||
}
|
||||
|
||||
if (packet != null) {
|
||||
@@ -1,19 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 1 Feb 2025 19:52:39 +0300
|
||||
Subject: [PATCH] Optimize canSee checks
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||
index dccf4d4b1067e1b09e38cabeae82185929494b62..55da7420dc3dfff468529a0f101f864dbefe3c7c 100644
|
||||
--- a/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1258,7 +1258,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
flag = flag && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
|
||||
// Paper end - Configurable entity tracking range by Y
|
||||
// CraftBukkit start - respect vanish API
|
||||
- if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
|
||||
+ if (flag && !player.getBukkitEntity().canSeeChunkMapUpdatePlayer(this.entity.getBukkitEntity())) { // Paper - only consider hits // DivineMC - optimize canSee checks
|
||||
flag = false;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -1,309 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Tue, 4 Feb 2025 01:49:17 +0300
|
||||
Subject: [PATCH] Implement NoChatReports
|
||||
|
||||
|
||||
diff --git a/net/minecraft/network/FriendlyByteBuf.java b/net/minecraft/network/FriendlyByteBuf.java
|
||||
index d1daa3443446f47e2215f0c7c5823da58e053bab..61b1440ee7909946cd2d7a4d8622f79c6f6ac76b 100644
|
||||
--- a/net/minecraft/network/FriendlyByteBuf.java
|
||||
+++ b/net/minecraft/network/FriendlyByteBuf.java
|
||||
@@ -105,7 +105,28 @@ public class FriendlyByteBuf extends ByteBuf {
|
||||
return this;
|
||||
}
|
||||
|
||||
+ @SuppressWarnings({"unchecked", "rawtypes"}) // DivineMC - Implement NoChatReports
|
||||
public <T> T readJsonWithCodec(Codec<T> codec) {
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ if (codec == net.minecraft.network.protocol.status.ServerStatus.CODEC) {
|
||||
+ JsonElement jsonElement = GsonHelper.fromJson(GSON, this.readUtf(), JsonElement.class);
|
||||
+ DataResult dataResult = codec.parse(JsonOps.INSTANCE, jsonElement);
|
||||
+ Object result;
|
||||
+ try {
|
||||
+ result = dataResult.getOrThrow(string -> new DecoderException("Failed to decode json: " + string));
|
||||
+ } catch (Throwable e) {
|
||||
+ throw new RuntimeException("Unable to decode json!", e);
|
||||
+ }
|
||||
+
|
||||
+ if (jsonElement.getAsJsonObject().has("preventsChatReports")) {
|
||||
+ ((net.minecraft.network.protocol.status.ServerStatus) result).setPreventsChatReports(jsonElement.getAsJsonObject().get("preventsChatReports").getAsBoolean());
|
||||
+ }
|
||||
+
|
||||
+ return (T) (result);
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
JsonElement jsonElement = GsonHelper.fromJson(GSON, this.readUtf(), JsonElement.class);
|
||||
DataResult<T> dataResult = codec.parse(JsonOps.INSTANCE, jsonElement);
|
||||
return dataResult.getOrThrow(exception -> new DecoderException("Failed to decode json: " + exception));
|
||||
@@ -117,6 +138,19 @@ public class FriendlyByteBuf extends ByteBuf {
|
||||
}
|
||||
public <T> void writeJsonWithCodec(Codec<T> codec, T value, int maxLength) {
|
||||
// Paper end - Adventure; add max length parameter
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsAddQueryData && codec == net.minecraft.network.protocol.status.ServerStatus.CODEC) {
|
||||
+ DataResult<JsonElement> dataResult = codec.encodeStart(JsonOps.INSTANCE, value);
|
||||
+ JsonElement element = dataResult.getOrThrow(string -> new EncoderException("Failed to encode: " + string + " " + value));
|
||||
+
|
||||
+ element.getAsJsonObject().addProperty("preventsChatReports", true);
|
||||
+
|
||||
+ this.writeUtf(GSON.toJson(element));
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
DataResult<JsonElement> dataResult = codec.encodeStart(JsonOps.INSTANCE, value);
|
||||
this.writeUtf(GSON.toJson(dataResult.getOrThrow(exception -> new EncoderException("Failed to encode: " + exception + " " + value))), maxLength); // Paper - Adventure; add max length parameter
|
||||
}
|
||||
diff --git a/net/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket.java b/net/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket.java
|
||||
index 07943553b562b95076bdce232d6f0796f469400f..61ecf4c6ae37b13ed42dff8d4165d32f3a5cc0c9 100644
|
||||
--- a/net/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ServerboundChatCommandSignedPacket.java
|
||||
@@ -36,4 +36,15 @@ public record ServerboundChatCommandSignedPacket(
|
||||
public void handle(ServerGamePacketListener handler) {
|
||||
handler.handleSignedChatCommand(this);
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ @Override
|
||||
+ public ArgumentSignatures argumentSignatures() {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ return ArgumentSignatures.EMPTY;
|
||||
+ }
|
||||
+
|
||||
+ return argumentSignatures;
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
}
|
||||
diff --git a/net/minecraft/network/protocol/game/ServerboundChatPacket.java b/net/minecraft/network/protocol/game/ServerboundChatPacket.java
|
||||
index b5afc05924ae899e020c303c8b86398e1d4ab8a0..3af0436ac2dff04cfaa1b3dda11a5417f2c0890c 100644
|
||||
--- a/net/minecraft/network/protocol/game/ServerboundChatPacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ServerboundChatPacket.java
|
||||
@@ -36,4 +36,16 @@ public record ServerboundChatPacket(String message, Instant timeStamp, long salt
|
||||
public void handle(ServerGamePacketListener handler) {
|
||||
handler.handleChat(this);
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ @Override
|
||||
+ @Nullable
|
||||
+ public MessageSignature signature() {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ return signature;
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
}
|
||||
diff --git a/net/minecraft/network/protocol/game/ServerboundChatSessionUpdatePacket.java b/net/minecraft/network/protocol/game/ServerboundChatSessionUpdatePacket.java
|
||||
index 1df628ac0b414511aaed6e09d78f884c4170f730..d94858facc06d57139e953796ee09dad17648dbb 100644
|
||||
--- a/net/minecraft/network/protocol/game/ServerboundChatSessionUpdatePacket.java
|
||||
+++ b/net/minecraft/network/protocol/game/ServerboundChatSessionUpdatePacket.java
|
||||
@@ -26,6 +26,19 @@ public record ServerboundChatSessionUpdatePacket(RemoteChatSession.Data chatSess
|
||||
|
||||
@Override
|
||||
public void handle(ServerGamePacketListener handler) {
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ var impl = (net.minecraft.server.network.ServerGamePacketListenerImpl) handler;
|
||||
+
|
||||
+ if (!impl.getPlayer().getServer().isSingleplayerOwner(impl.getPlayer().getGameProfile())) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsDemandOnClient) {
|
||||
+ impl.disconnect(net.minecraft.network.chat.Component.literal(org.bxteam.divinemc.DivineConfig.noChatReportsDisconnectDemandOnClientMessage));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
handler.handleChatSessionUpdate(this);
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/network/protocol/status/ServerStatus.java b/net/minecraft/network/protocol/status/ServerStatus.java
|
||||
index 30bd254542d631676494f349ff3f44f52d54ab2f..6c728ae3b58bc1b8449d34c6c74091612b79f39e 100644
|
||||
--- a/net/minecraft/network/protocol/status/ServerStatus.java
|
||||
+++ b/net/minecraft/network/protocol/status/ServerStatus.java
|
||||
@@ -15,13 +15,7 @@ import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.ComponentSerialization;
|
||||
|
||||
-public record ServerStatus(
|
||||
- Component description,
|
||||
- Optional<ServerStatus.Players> players,
|
||||
- Optional<ServerStatus.Version> version,
|
||||
- Optional<ServerStatus.Favicon> favicon,
|
||||
- boolean enforcesSecureChat
|
||||
-) {
|
||||
+public final class ServerStatus {
|
||||
public static final Codec<ServerStatus> CODEC = RecordCodecBuilder.create(
|
||||
instance -> instance.group(
|
||||
ComponentSerialization.CODEC.lenientOptionalFieldOf("description", CommonComponents.EMPTY).forGetter(ServerStatus::description),
|
||||
@@ -33,6 +27,63 @@ public record ServerStatus(
|
||||
.apply(instance, ServerStatus::new)
|
||||
);
|
||||
|
||||
+ // DivineMC start - Implement NoChatReports - convert to class
|
||||
+ private final Component description;
|
||||
+ private final Optional<Players> players;
|
||||
+ private final Optional<Version> version;
|
||||
+ private final Optional<Favicon> favicon;
|
||||
+ private final boolean enforcesSecureChat;
|
||||
+ private boolean preventsChatReports;
|
||||
+
|
||||
+ public ServerStatus(
|
||||
+ Component description,
|
||||
+ Optional<Players> players,
|
||||
+ Optional<Version> version,
|
||||
+ Optional<Favicon> favicon,
|
||||
+ boolean enforcesSecureChat
|
||||
+ ) {
|
||||
+ this.description = description;
|
||||
+ this.players = players;
|
||||
+ this.version = version;
|
||||
+ this.favicon = favicon;
|
||||
+ this.enforcesSecureChat = enforcesSecureChat;
|
||||
+ }
|
||||
+
|
||||
+ public Component description() {
|
||||
+ return description;
|
||||
+ }
|
||||
+
|
||||
+ public Optional<Players> players() {
|
||||
+ return players;
|
||||
+ }
|
||||
+
|
||||
+ public Optional<Version> version() {
|
||||
+ return version;
|
||||
+ }
|
||||
+
|
||||
+ public Optional<Favicon> favicon() {
|
||||
+ return favicon;
|
||||
+ }
|
||||
+
|
||||
+ public boolean enforcesSecureChat() {
|
||||
+ return enforcesSecureChat;
|
||||
+ }
|
||||
+
|
||||
+ public boolean preventsChatReports() {
|
||||
+ var self = (ServerStatus) (Object) this;
|
||||
+
|
||||
+ if (self.version().isPresent() && self.version().get().protocol() < 759
|
||||
+ && self.version().get().protocol() > 0)
|
||||
+ return true;
|
||||
+
|
||||
+ return this.preventsChatReports;
|
||||
+ }
|
||||
+
|
||||
+ public void setPreventsChatReports(boolean prevents) {
|
||||
+ this.preventsChatReports = prevents;
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
+
|
||||
public record Favicon(byte[] iconBytes) {
|
||||
private static final String PREFIX = "data:image/png;base64,";
|
||||
public static final Codec<ServerStatus.Favicon> CODEC = Codec.STRING.comapFlatMap(string -> {
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index 9fcdff2be139296f4e14b54c33cc795efdff0c7f..64c3bbe540599e5195f0cc89635bff2c56d1a320 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -668,6 +668,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
|
||||
@Override
|
||||
public boolean enforceSecureProfile() {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) return false; // DivineMC - Implement NoChatReports
|
||||
DedicatedServerProperties properties = this.getProperties();
|
||||
// Paper start - Add setting for proxy online mode status
|
||||
return properties.enforceSecureProfile
|
||||
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index 801dd76a2c7f76fc6fdb7167cbf3ab1310be36c9..4fa55fac5dab26a505cba2c1876e9459a582da12 100644
|
||||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -312,10 +312,64 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
}
|
||||
|
||||
public void send(Packet<?> packet) {
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ Object self = this;
|
||||
+ boolean cancel = false;
|
||||
+
|
||||
+ if (self instanceof ServerGamePacketListenerImpl listener) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsDebugLog && packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket chat) {
|
||||
+ MinecraftServer.LOGGER.info("Sending message: {}", chat.unsignedContent() != null ? chat.unsignedContent()
|
||||
+ : chat.body().content());
|
||||
+ }
|
||||
+
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsConvertToGameMessage) {
|
||||
+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket chat) {
|
||||
+ packet = new net.minecraft.network.protocol.game.ClientboundSystemChatPacket(chat.chatType().decorate(
|
||||
+ chat.unsignedContent() != null ? chat.unsignedContent()
|
||||
+ : Component.literal(chat.body().content())
|
||||
+ ), false);
|
||||
+
|
||||
+ cancel = true;
|
||||
+ listener.send(packet);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (cancel) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
this.send(packet, null);
|
||||
}
|
||||
|
||||
public void send(Packet<?> packet, @Nullable PacketSendListener listener) {
|
||||
+ // DivineMC start - Implement NoChatReports
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) {
|
||||
+ Object self = this;
|
||||
+ boolean cancel = false;
|
||||
+
|
||||
+ if (self instanceof ServerGamePacketListenerImpl listenerImpl) {
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsDebugLog && packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket chat) {
|
||||
+ MinecraftServer.LOGGER.info("Sending message: {}", chat.unsignedContent() != null ? chat.unsignedContent()
|
||||
+ : chat.body().content());
|
||||
+ }
|
||||
+
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsConvertToGameMessage) {
|
||||
+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket chat && listener != null) {
|
||||
+ cancel = true;
|
||||
+ listenerImpl.send(chat);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if (cancel) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Implement NoChatReports
|
||||
// CraftBukkit start
|
||||
if (packet == null || this.processedDisconnect) { // Spigot
|
||||
return;
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 3d8c1c5aa922ec0417388a1ff27d423cdb6d1351..6cbd57650f1f966955ee14039bca8ceb164599cd 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -274,7 +274,7 @@ public abstract class PlayerList {
|
||||
!_boolean,
|
||||
_boolean2,
|
||||
player.createCommonSpawnInfo(serverLevel),
|
||||
- this.server.enforceSecureProfile()
|
||||
+ org.bxteam.divinemc.DivineConfig.noChatReportsEnabled || this.server.enforceSecureProfile() // DivineMC - Implement NoChatReports
|
||||
)
|
||||
);
|
||||
player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
|
||||
@@ -1333,6 +1333,7 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public boolean verifyChatTrusted(PlayerChatMessage message) { // Paper - private -> public
|
||||
+ if (org.bxteam.divinemc.DivineConfig.noChatReportsEnabled) return true; // DivineMC - Implement NoChatReports
|
||||
return message.hasSignature() && !message.hasExpiredServer(Instant.now());
|
||||
}
|
||||
|
||||
@@ -1,275 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Tue, 4 Feb 2025 19:52:24 +0300
|
||||
Subject: [PATCH] Optimize Structure Generation
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java b/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
index 63143ceec98f7a84ec4064d05e8f88c11200172f..02f67af9c312f3d9213af1e410986165dcf618a4 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/pools/JigsawPlacement.java
|
||||
@@ -4,6 +4,8 @@ import com.google.common.collect.Lists;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.LinkedHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Holder;
|
||||
@@ -292,6 +294,108 @@ public class JigsawPlacement {
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ private boolean structureLayoutOptimizer$optimizeJigsawConnecting(StructureTemplate.JigsawBlockInfo jigsaw1, StructureTemplate.JigsawBlockInfo jigsaw2) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer) {
|
||||
+ return JigsawBlock.canAttach(jigsaw1, jigsaw2);
|
||||
+ }
|
||||
+ return org.bxteam.divinemc.util.structure.GeneralUtils.canJigsawsAttach(jigsaw1, jigsaw2);
|
||||
+ }
|
||||
+
|
||||
+ private void structureLayoutOptimizer$replaceVoxelShape3(MutableObject<VoxelShape> instance, BoundingBox pieceBounds) {
|
||||
+ org.bxteam.divinemc.util.structure.TrojanVoxelShape trojanVoxelShape = new org.bxteam.divinemc.util.structure.TrojanVoxelShape(new org.bxteam.divinemc.util.structure.BoxOctree(AABB.of(pieceBounds)));
|
||||
+ instance.setValue(trojanVoxelShape);
|
||||
+ }
|
||||
+
|
||||
+ private void structureLayoutOptimizer$replaceVoxelShape4(MutableObject<VoxelShape> instance, BoundingBox pieceBounds) {
|
||||
+ if (instance.getValue() instanceof org.bxteam.divinemc.util.structure.TrojanVoxelShape trojanVoxelShape) {
|
||||
+ trojanVoxelShape.boxOctree.addBox(AABB.of(pieceBounds));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private List<StructurePoolElement> structureLayoutOptimizer$removeDuplicateTemplatePoolElementLists(StructureTemplatePool instance, RandomSource random) {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer || !org.bxteam.divinemc.DivineConfig.deduplicateShuffledTemplatePoolElementList) {
|
||||
+ return instance.getShuffledTemplates(random);
|
||||
+ }
|
||||
+
|
||||
+ // Linked hashset keeps order of elements.
|
||||
+ LinkedHashSet<StructurePoolElement> uniquePieces = new LinkedHashSet<>((instance).rawTemplates.size());
|
||||
+
|
||||
+ // Don't use addAll. Want to keep it simple in case of inefficiency in collection's addAll.
|
||||
+ // Set will ignore duplicates after first appearance of an element.
|
||||
+ for (StructurePoolElement piece : instance.getShuffledTemplates(random)) {
|
||||
+ //noinspection UseBulkOperation
|
||||
+ uniquePieces.add(piece);
|
||||
+ }
|
||||
+
|
||||
+ // Move the elements from set to the list in the same order.
|
||||
+ int uniquePiecesFound = uniquePieces.size();
|
||||
+ List<StructurePoolElement> deduplicatedListOfPieces = new ArrayList<>(uniquePiecesFound);
|
||||
+ for (int i = 0; i < uniquePiecesFound; i++) {
|
||||
+ deduplicatedListOfPieces.add(uniquePieces.removeFirst());
|
||||
+ }
|
||||
+
|
||||
+ return deduplicatedListOfPieces;
|
||||
+ }
|
||||
+
|
||||
+ private ArrayList<StructurePoolElement> structureLayoutOptimizer$skipDuplicateTemplatePoolElementLists1() {
|
||||
+ // Swap with trojan list, so we can record what pieces we visited
|
||||
+ return org.bxteam.divinemc.DivineConfig.deduplicateShuffledTemplatePoolElementList ? Lists.newArrayList() : new org.bxteam.divinemc.util.structure.TrojanArrayList<>();
|
||||
+ }
|
||||
+
|
||||
+ private List structureLayoutOptimizer$skipBlockedJigsaws(
|
||||
+ List original,
|
||||
+ boolean useExpansionHack,
|
||||
+ MutableObject<VoxelShape> voxelShapeMutableObject,
|
||||
+ StructurePoolElement structurePoolElement,
|
||||
+ StructureTemplate.StructureBlockInfo parentJigsawBlockInfo,
|
||||
+ BlockPos parentTargetPosition)
|
||||
+ {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer) {
|
||||
+ return original;
|
||||
+ }
|
||||
+ if (voxelShapeMutableObject.getValue() instanceof org.bxteam.divinemc.util.structure.TrojanVoxelShape trojanVoxelShape) {
|
||||
+ // If rigid and target position is already an invalid spot, do not run rest of logic.
|
||||
+ StructureTemplatePool.Projection candidatePlacementBehavior = structurePoolElement.getProjection();
|
||||
+ boolean isCandidateRigid = candidatePlacementBehavior == StructureTemplatePool.Projection.RIGID;
|
||||
+ if (isCandidateRigid && (!trojanVoxelShape.boxOctree.boundaryContains(parentTargetPosition) || trojanVoxelShape.boxOctree.withinAnyBox(parentTargetPosition))) {
|
||||
+ return new ArrayList<>();
|
||||
+ }
|
||||
+ }
|
||||
+ return original;
|
||||
+ }
|
||||
+
|
||||
+ private List<Rotation> structureLayoutOptimizer$skipDuplicateTemplatePoolElementLists2(List<Rotation> original,
|
||||
+ List<StructurePoolElement> list,
|
||||
+ StructurePoolElement structurepoolelement1)
|
||||
+ {
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer) {
|
||||
+ return original;
|
||||
+ }
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.deduplicateShuffledTemplatePoolElementList && list instanceof org.bxteam.divinemc.util.structure.TrojanArrayList<net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement> trojanArrayList) {
|
||||
+ // Do not run this piece's logic since we already checked its 4 rotations in the past.
|
||||
+ if (trojanArrayList.elementsAlreadyParsed.contains(structurepoolelement1)) {
|
||||
+
|
||||
+ // Prime the random with the random calls we would've skipped.
|
||||
+ // Maintains vanilla compat.
|
||||
+ for (Rotation rotation1 : original) {
|
||||
+ structurepoolelement1.getShuffledJigsawBlocks(this.structureTemplateManager, BlockPos.ZERO, rotation1, this.random);
|
||||
+ }
|
||||
+
|
||||
+ // Short circuit the Rotation loop
|
||||
+ return new ArrayList<>();
|
||||
+ }
|
||||
+ // Record piece as it will go through the 4 rotation checks for spawning.
|
||||
+ else {
|
||||
+ trojanArrayList.elementsAlreadyParsed.add(structurepoolelement1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Allow the vanilla code to run normally.
|
||||
+ return original;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
+
|
||||
void tryPlacingChildren(
|
||||
PoolElementStructurePiece piece,
|
||||
MutableObject<VoxelShape> free,
|
||||
@@ -349,9 +453,9 @@ public class JigsawPlacement {
|
||||
mutableObject1 = free;
|
||||
}
|
||||
|
||||
- List<StructurePoolElement> list = Lists.newArrayList();
|
||||
+ List<StructurePoolElement> list = structureLayoutOptimizer$skipDuplicateTemplatePoolElementLists1(); // DivineMC - Optimize Structure Generation
|
||||
if (depth != this.maxDepth) {
|
||||
- list.addAll(holder.value().getShuffledTemplates(this.random));
|
||||
+ list.addAll(structureLayoutOptimizer$removeDuplicateTemplatePoolElementLists(holder.value(), this.random)); // DivineMC - Optimize Structure Generation
|
||||
}
|
||||
|
||||
list.addAll(fallback.value().getShuffledTemplates(this.random));
|
||||
@@ -362,10 +466,14 @@ public class JigsawPlacement {
|
||||
break;
|
||||
}
|
||||
|
||||
- for (Rotation rotation1 : Rotation.getShuffled(this.random)) {
|
||||
- List<StructureTemplate.JigsawBlockInfo> shuffledJigsawBlocks = structurePoolElement.getShuffledJigsawBlocks(
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ for (Rotation rotation1 : structureLayoutOptimizer$skipDuplicateTemplatePoolElementLists2(Rotation.getShuffled(this.random), list, structurePoolElement)) {
|
||||
+ List<StructureTemplate.JigsawBlockInfo> shuffledJigsawBlocks = structureLayoutOptimizer$skipBlockedJigsaws(
|
||||
+ structurePoolElement.getShuffledJigsawBlocks(
|
||||
this.structureTemplateManager, BlockPos.ZERO, rotation1, this.random
|
||||
+ ), useExpansionHack, mutableObject1, structurePoolElement, structureBlockInfo, blockPos1
|
||||
);
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
BoundingBox boundingBox1 = structurePoolElement.getBoundingBox(this.structureTemplateManager, BlockPos.ZERO, rotation1);
|
||||
int i2;
|
||||
if (useExpansionHack && boundingBox1.getYSpan() <= 16) {
|
||||
@@ -398,7 +506,7 @@ public class JigsawPlacement {
|
||||
}
|
||||
|
||||
for (StructureTemplate.JigsawBlockInfo jigsawBlockInfo1 : shuffledJigsawBlocks) {
|
||||
- if (JigsawBlock.canAttach(jigsawBlockInfo, jigsawBlockInfo1)) {
|
||||
+ if (structureLayoutOptimizer$optimizeJigsawConnecting(jigsawBlockInfo, jigsawBlockInfo1)) { // DivineMC - Optimize Structure Generation
|
||||
BlockPos blockPos2 = jigsawBlockInfo1.info().pos();
|
||||
BlockPos blockPos3 = blockPos1.subtract(blockPos2);
|
||||
BoundingBox boundingBox2 = structurePoolElement.getBoundingBox(this.structureTemplateManager, blockPos3, rotation1);
|
||||
@@ -427,9 +535,26 @@ public class JigsawPlacement {
|
||||
boundingBox3.encapsulate(new BlockPos(boundingBox3.minX(), boundingBox3.minY() + max, boundingBox3.minZ()));
|
||||
}
|
||||
|
||||
- if (!Shapes.joinIsNotEmpty(
|
||||
- mutableObject1.getValue(), Shapes.create(AABB.of(boundingBox3).deflate(0.25)), BooleanOp.ONLY_SECOND
|
||||
- )) {
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ boolean internal$joinIsNotEmpty;
|
||||
+ VoxelShape parentBounds = mutableObject1.getValue();
|
||||
+ java.util.function.Supplier<Boolean> original = () -> Shapes.joinIsNotEmpty(
|
||||
+ parentBounds, Shapes.create(AABB.of(boundingBox3).deflate(0.25)), BooleanOp.ONLY_SECOND
|
||||
+ );
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer) {
|
||||
+ if (parentBounds instanceof org.bxteam.divinemc.util.structure.TrojanVoxelShape trojanVoxelShape) {
|
||||
+ AABB pieceAABB = AABB.of(boundingBox3).deflate(0.25D);
|
||||
+
|
||||
+ // Have to inverse because of an ! outside our wrap
|
||||
+ internal$joinIsNotEmpty = !trojanVoxelShape.boxOctree.withinBoundsButNotIntersectingChildren(pieceAABB);
|
||||
+ } else {
|
||||
+ internal$joinIsNotEmpty = original.get();
|
||||
+ }
|
||||
+ } else {
|
||||
+ internal$joinIsNotEmpty = original.get();
|
||||
+ }
|
||||
+ if (!internal$joinIsNotEmpty) {
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
mutableObject1.setValue(
|
||||
Shapes.joinUnoptimized(
|
||||
mutableObject1.getValue(), Shapes.create(AABB.of(boundingBox3)), BooleanOp.ONLY_FIRST
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement.java b/net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement.java
|
||||
index 4a6da3648c513a6cce16cf71246937d2d0ad014d..6af4c9026e814dee1ed4c7593ad00b5f8af9b979 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/pools/SinglePoolElement.java
|
||||
@@ -119,8 +119,16 @@ public class SinglePoolElement extends StructurePoolElement {
|
||||
StructureTemplateManager structureTemplateManager, BlockPos pos, Rotation rotation, RandomSource random
|
||||
) {
|
||||
List<StructureTemplate.JigsawBlockInfo> jigsaws = this.getTemplate(structureTemplateManager).getJigsaws(pos, rotation);
|
||||
- Util.shuffle(jigsaws, random);
|
||||
- sortBySelectionPriority(jigsaws);
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer) {
|
||||
+ structureLayoutOptimizer$fasterJigsawListShuffling1(jigsaws, random);
|
||||
+ structureLayoutOptimizer$fasterJigsawListShuffling2(jigsaws);
|
||||
+ } else {
|
||||
+ Util.shuffle(jigsaws, random);
|
||||
+ sortBySelectionPriority(jigsaws);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
+
|
||||
return jigsaws;
|
||||
}
|
||||
|
||||
@@ -191,4 +199,12 @@ public class SinglePoolElement extends StructurePoolElement {
|
||||
public String toString() {
|
||||
return "Single[" + this.template + "]";
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ private void structureLayoutOptimizer$fasterJigsawListShuffling1(List<StructureTemplate.JigsawBlockInfo> list, RandomSource randomSource) {
|
||||
+ org.bxteam.divinemc.util.structure.GeneralUtils.shuffleAndPrioritize(list, randomSource);
|
||||
+ }
|
||||
+
|
||||
+ private void structureLayoutOptimizer$fasterJigsawListShuffling2(List<StructureTemplate.JigsawBlockInfo> structureBlockInfos) { }
|
||||
+ // Quiil end - Optimize Structure Generation
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
index a37eb2e29b4577ebc711e8ef7b47fbbc3bc66897..45d6fbeeaac577bb35adb69fd344b9486953ea03 100644
|
||||
--- a/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
|
||||
@@ -249,6 +249,12 @@ public class StructureTemplate {
|
||||
return transform(pos, decorator.getMirror(), decorator.getRotation(), decorator.getRotationPivot());
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ private List<StructureTemplate.StructureBlockInfo> structureLayoutOptimizer$shrinkStructureTemplateBlocksList(StructureTemplate.Palette palette, BlockPos offset, StructurePlaceSettings settings) {
|
||||
+ return org.bxteam.divinemc.util.structure.StructureTemplateOptimizer.getStructureBlockInfosInBounds(palette, offset, settings);
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
+
|
||||
public boolean placeInWorld(ServerLevelAccessor serverLevel, BlockPos offset, BlockPos pos, StructurePlaceSettings settings, RandomSource random, int flags) {
|
||||
if (this.palettes.isEmpty()) {
|
||||
return false;
|
||||
@@ -266,7 +272,11 @@ public class StructureTemplate {
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
- List<StructureTemplate.StructureBlockInfo> list = settings.getRandomPalette(this.palettes, offset).blocks();
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ List<StructureTemplate.StructureBlockInfo> list = org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer
|
||||
+ ? structureLayoutOptimizer$shrinkStructureTemplateBlocksList(settings.getRandomPalette(this.palettes, offset), offset, settings)
|
||||
+ : settings.getRandomPalette(this.palettes, offset).blocks();
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
if ((!list.isEmpty() || !settings.isIgnoreEntities() && !this.entityInfoList.isEmpty())
|
||||
&& this.size.getX() >= 1
|
||||
&& this.size.getY() >= 1
|
||||
@@ -890,7 +900,11 @@ public class StructureTemplate {
|
||||
private List<StructureTemplate.JigsawBlockInfo> cachedJigsaws;
|
||||
|
||||
Palette(List<StructureTemplate.StructureBlockInfo> blocks) {
|
||||
- this.blocks = blocks;
|
||||
+ // DivineMC start - Optimize Structure Generation
|
||||
+ this.blocks = org.bxteam.divinemc.DivineConfig.enableStructureLayoutOptimizer
|
||||
+ ? new org.bxteam.divinemc.util.structure.PalettedStructureBlockInfoList(blocks)
|
||||
+ : blocks;
|
||||
+ // DivineMC end - Optimize Structure Generation
|
||||
}
|
||||
|
||||
public List<StructureTemplate.JigsawBlockInfo> jigsaws() {
|
||||
@@ -1,38 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Wed, 5 Feb 2025 17:48:56 +0300
|
||||
Subject: [PATCH] Verify Minecraft EULA earlier
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java
|
||||
index 1485186d4989874ef89c4e83830f26358a43759c..c4f9b67c92e4c7e8015f637fe633a9e8da276e5c 100644
|
||||
--- a/net/minecraft/server/Main.java
|
||||
+++ b/net/minecraft/server/Main.java
|
||||
@@ -123,7 +123,6 @@ public class Main {
|
||||
dedicatedServerSettings.forceSave();
|
||||
RegionFileVersion.configure(dedicatedServerSettings.getProperties().regionFileComression);
|
||||
Path path2 = Paths.get("eula.txt");
|
||||
- Eula eula = new Eula(path2);
|
||||
// Paper start - load config files early for access below if needed
|
||||
org.bukkit.configuration.file.YamlConfiguration bukkitConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("bukkit-settings"));
|
||||
org.bukkit.configuration.file.YamlConfiguration spigotConfiguration = io.papermc.paper.configuration.PaperConfigurations.loadLegacyConfigFile((File) optionSet.valueOf("spigot-settings"));
|
||||
@@ -146,19 +145,6 @@ public class Main {
|
||||
return;
|
||||
}
|
||||
|
||||
- // Spigot start
|
||||
- boolean eulaAgreed = Boolean.getBoolean("com.mojang.eula.agree");
|
||||
- if (eulaAgreed) {
|
||||
- LOGGER.error("You have used the Spigot command line EULA agreement flag.");
|
||||
- LOGGER.error("By using this setting you are indicating your agreement to Mojang's EULA (https://aka.ms/MinecraftEULA).");
|
||||
- LOGGER.error("If you do not agree to the above EULA please stop your server and remove this flag immediately.");
|
||||
- }
|
||||
- if (!eula.hasAgreedToEULA() && !eulaAgreed) {
|
||||
- // Spigot end
|
||||
- LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info.");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
// Paper start - Detect headless JRE
|
||||
String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
|
||||
if (awtException != null) {
|
||||
@@ -1,18 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 23 Feb 2025 01:03:59 +0300
|
||||
Subject: [PATCH] Configurable MC-67
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 3943789e241f6bb6bc165099b1fb585463cf3d86..07e8bda8eb200d5a7554e0319e1a00dc85454e1a 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -4017,6 +4017,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public boolean canTeleport(Level fromLevel, Level toLevel) {
|
||||
+ if (!fromLevel.divineConfig.allowEntityPortalWithPassenger && (this.isPassenger() || this.isVehicle())) return false; // DivineMC - Allow entity teleport with passenger
|
||||
if (!this.isAlive() || !this.valid) return false; // Paper - Fix item duplication and teleport issues
|
||||
if (fromLevel.dimension() == Level.END && toLevel.dimension() == Level.OVERWORLD) {
|
||||
for (Entity entity : this.getPassengers()) {
|
||||
@@ -1,44 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 23 Feb 2025 01:04:29 +0300
|
||||
Subject: [PATCH] Option to disable saving of snowball and firework
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
index c7ae41b2cbc1eb85a6eb9c16813bd326fb8f49f0..e6764ee35f9d9d20a7693d50ea61b703867e3c79 100644
|
||||
--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
+++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
|
||||
@@ -364,4 +364,14 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
|
||||
double d1 = entity.position().z - this.position().z;
|
||||
return DoubleDoubleImmutablePair.of(d, d1);
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Option to disable saving firework
|
||||
+ @Override
|
||||
+ public boolean shouldBeSaved() {
|
||||
+ if (this.level().divineConfig.disableFireworkSaving) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return super.shouldBeSaved();
|
||||
+ }
|
||||
+ // DivineMC end - Option to disable saving firework
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/projectile/Snowball.java b/net/minecraft/world/entity/projectile/Snowball.java
|
||||
index cad1f8cb68ef9615587e651a3120f68a3c32add0..18298f3ba544e07110ea8d5b15ae753f7e3de65a 100644
|
||||
--- a/net/minecraft/world/entity/projectile/Snowball.java
|
||||
+++ b/net/minecraft/world/entity/projectile/Snowball.java
|
||||
@@ -100,4 +100,14 @@ public class Snowball extends ThrowableItemProjectile {
|
||||
this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Option to disable snowball saving
|
||||
+ @Override
|
||||
+ public boolean shouldBeSaved() {
|
||||
+ if (this.level().divineConfig.disableSnowballSaving) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return super.shouldBeSaved();
|
||||
+ }
|
||||
+ // DivineMC end - Option to disable snowball saving
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Mon, 24 Feb 2025 19:10:17 +0300
|
||||
Subject: [PATCH] lithium: fast_util
|
||||
|
||||
|
||||
diff --git a/net/minecraft/core/Direction.java b/net/minecraft/core/Direction.java
|
||||
index 216f97207dac88cc1dc3df59c6ee8a62c7614b4a..05c7de5729466786a0196fa5f91eccc3cfffc675 100644
|
||||
--- a/net/minecraft/core/Direction.java
|
||||
+++ b/net/minecraft/core/Direction.java
|
||||
@@ -217,7 +217,7 @@ public enum Direction implements StringRepresentable, ca.spottedleaf.moonrise.pa
|
||||
}
|
||||
|
||||
public Direction getOpposite() {
|
||||
- return this.opposite; // Paper - optimise collisions
|
||||
+ return VALUES[this.oppositeIndex]; // DivineMC - lithium: fast_util
|
||||
}
|
||||
|
||||
public Direction getClockWise(Direction.Axis axis) {
|
||||
@@ -350,7 +350,7 @@ public enum Direction implements StringRepresentable, ca.spottedleaf.moonrise.pa
|
||||
}
|
||||
|
||||
public static Direction getRandom(RandomSource random) {
|
||||
- return Util.getRandom(VALUES, random);
|
||||
+ return VALUES[random.nextInt(VALUES.length)]; // DivineMC - lithium: fast_util
|
||||
}
|
||||
|
||||
public static Direction getApproximateNearest(double x, double y, double z) {
|
||||
diff --git a/net/minecraft/world/phys/AABB.java b/net/minecraft/world/phys/AABB.java
|
||||
index 54807bb4b4189ceaded1f78a1a9ab85ce40ab2b1..977642da91cf3bace9182e36c10512c8a1830503 100644
|
||||
--- a/net/minecraft/world/phys/AABB.java
|
||||
+++ b/net/minecraft/world/phys/AABB.java
|
||||
@@ -18,6 +18,15 @@ public class AABB {
|
||||
public final double maxY;
|
||||
public final double maxZ;
|
||||
|
||||
+ // DivineMC start - lithium: fast_util
|
||||
+ static {
|
||||
+ assert Direction.Axis.X.ordinal() == 0;
|
||||
+ assert Direction.Axis.Y.ordinal() == 1;
|
||||
+ assert Direction.Axis.Z.ordinal() == 2;
|
||||
+ assert Direction.Axis.values().length == 3;
|
||||
+ }
|
||||
+ // DivineMC end - lithium: fast_util
|
||||
+
|
||||
public AABB(double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
this.minX = Math.min(x1, x2);
|
||||
this.minY = Math.min(y1, y2);
|
||||
@@ -79,11 +88,33 @@ public class AABB {
|
||||
}
|
||||
|
||||
public double min(Direction.Axis axis) {
|
||||
- return axis.choose(this.minX, this.minY, this.minZ);
|
||||
+ // DivineMC start - lithium: fast_util
|
||||
+ switch (axis.ordinal()) {
|
||||
+ case 0: // X
|
||||
+ return this.minX;
|
||||
+ case 1: // Y
|
||||
+ return this.minY;
|
||||
+ case 2: // Z
|
||||
+ return this.minZ;
|
||||
+ }
|
||||
+
|
||||
+ throw new IllegalArgumentException();
|
||||
+ // DivineMC end - lithium: fast_util
|
||||
}
|
||||
|
||||
public double max(Direction.Axis axis) {
|
||||
- return axis.choose(this.maxX, this.maxY, this.maxZ);
|
||||
+ // DivineMC start - lithium: fast_util
|
||||
+ switch (axis.ordinal()) {
|
||||
+ case 0: // X
|
||||
+ return this.maxX;
|
||||
+ case 1: // Y
|
||||
+ return this.maxY;
|
||||
+ case 2: // Z
|
||||
+ return this.maxZ;
|
||||
+ }
|
||||
+
|
||||
+ throw new IllegalArgumentException();
|
||||
+ // DivineMC end - lithium: fast_util
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,107 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Mon, 24 Feb 2025 19:29:58 +0300
|
||||
Subject: [PATCH] Virtual Threads
|
||||
|
||||
|
||||
diff --git a/net/minecraft/Util.java b/net/minecraft/Util.java
|
||||
index 80a7a85e1a03a1ca406259207e1ae3b909b3284f..aa2d99de3d23d262542bfb1592fe084f94230f85 100644
|
||||
--- a/net/minecraft/Util.java
|
||||
+++ b/net/minecraft/Util.java
|
||||
@@ -97,7 +97,12 @@ public class Util {
|
||||
public static final TracingExecutor DIMENSION_DATA_IO_POOL = makeExtraIoExecutor("Dimension-Data-IO-Worker-"); // Paper - Separate dimension data IO pool
|
||||
private static final TracingExecutor DOWNLOAD_POOL = makeIoExecutor("Download-", true);
|
||||
// Paper start - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
|
||||
- public static final ExecutorService PROFILE_EXECUTOR = Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory() {
|
||||
+ // DivineMC start - Virtual Threads
|
||||
+ public static final ExecutorService PROFILE_EXECUTOR = org.bxteam.divinemc.DivineConfig.virtualThreadsEnabled && org.bxteam.divinemc.DivineConfig.virtualProfileLookupPool
|
||||
+ ? Executors.newVirtualThreadPerTaskExecutor()
|
||||
+ : Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory()
|
||||
+ {
|
||||
+ // DivineMC end - Virtual Threads
|
||||
|
||||
private final AtomicInteger count = new AtomicInteger();
|
||||
|
||||
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
|
||||
index 212d2bcfd34f7cb14e18a8af2cd296fc01d371f6..ec76e4f29ba96b31a24a5d195b852342a57e0bdb 100644
|
||||
--- a/net/minecraft/commands/Commands.java
|
||||
+++ b/net/minecraft/commands/Commands.java
|
||||
@@ -474,7 +474,7 @@ public class Commands {
|
||||
}
|
||||
|
||||
// Fixed pool, but with discard policy
|
||||
- public static final java.util.concurrent.ExecutorService COMMAND_SENDING_POOL = new java.util.concurrent.ThreadPoolExecutor(
|
||||
+ public static final java.util.concurrent.ExecutorService COMMAND_SENDING_POOL = org.bxteam.divinemc.DivineConfig.virtualThreadsEnabled && org.bxteam.divinemc.DivineConfig.virtualCommandBuilderScheduler ? java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor() : new java.util.concurrent.ThreadPoolExecutor( // DivineMC - Virtual Threads
|
||||
2, 2, 0, java.util.concurrent.TimeUnit.MILLISECONDS,
|
||||
new java.util.concurrent.LinkedBlockingQueue<>(),
|
||||
new com.google.common.util.concurrent.ThreadFactoryBuilder()
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 5a0c8791495aa522e511918ad0a24d9bbe6b5877..9d6fa3bced0ba5ab3443bdf4ce306598a8e4a31f 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -2710,8 +2710,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
}
|
||||
}
|
||||
|
||||
- public final java.util.concurrent.ExecutorService chatExecutor = java.util.concurrent.Executors.newCachedThreadPool(
|
||||
- new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper
|
||||
+ // DivineMC start - Virtual Threads
|
||||
+ public final java.util.concurrent.ExecutorService chatExecutor = org.bxteam.divinemc.DivineConfig.virtualThreadsEnabled && org.bxteam.divinemc.DivineConfig.virtualChatScheduler
|
||||
+ ? java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()
|
||||
+ : java.util.concurrent.Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper
|
||||
+ // DivineMC end - Virtual Threads
|
||||
public final ChatDecorator improvedChatDecorator = new io.papermc.paper.adventure.ImprovedChatDecorator(this); // Paper - adventure
|
||||
|
||||
public ChatDecorator getChatDecorator() {
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index a3ec8c92dae7735bb0b1ececc9851c829c486a53..02b4275d170cc854a7482f0e963394aee21171dd 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -808,8 +808,11 @@ public class ServerGamePacketListenerImpl
|
||||
}
|
||||
|
||||
// Paper start - AsyncTabCompleteEvent
|
||||
- private static final java.util.concurrent.ExecutorService TAB_COMPLETE_EXECUTOR = java.util.concurrent.Executors.newFixedThreadPool(4,
|
||||
- new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Tab Complete Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(MinecraftServer.LOGGER)).build());
|
||||
+ // DivineMC start - Virtual Threads
|
||||
+ private static final java.util.concurrent.ExecutorService TAB_COMPLETE_EXECUTOR = org.bxteam.divinemc.DivineConfig.virtualThreadsEnabled && org.bxteam.divinemc.DivineConfig.virtualTabCompleteScheduler
|
||||
+ ? java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()
|
||||
+ : java.util.concurrent.Executors.newFixedThreadPool(4, new com.google.common.util.concurrent.ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Tab Complete Thread - #%d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(MinecraftServer.LOGGER)).build());
|
||||
+ // DivineMC end - Virtual Threads
|
||||
// Paper end - AsyncTabCompleteEvent
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index 45ea5fa0ef57724acce46008c53f7fa216cf78ee..f4a9d49247d2124b03273c38b14ddf9661184749 100644
|
||||
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -55,7 +55,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
// CraftBukkit end
|
||||
private static final AtomicInteger UNIQUE_THREAD_ID = new AtomicInteger(0);
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
- private static final java.util.concurrent.ExecutorService authenticatorPool = java.util.concurrent.Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("User Authenticator #%d").setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)).build()); // Paper - Cache authenticator threads
|
||||
+ // DivineMC start - Virtual Threads
|
||||
+ private static final java.util.concurrent.ExecutorService authenticatorPool = org.bxteam.divinemc.DivineConfig.virtualThreadsEnabled && org.bxteam.divinemc.DivineConfig.virtualAuthenticatorScheduler
|
||||
+ ? java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()
|
||||
+ : java.util.concurrent.Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("User Authenticator #%d").setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)).build()); // Paper - Cache authenticator threads
|
||||
+ // DivineMC end - Virtual Threads
|
||||
private static final int MAX_TICKS_BEFORE_LOGIN = 600;
|
||||
private final byte[] challenge;
|
||||
final MinecraftServer server;
|
||||
diff --git a/net/minecraft/server/network/ServerTextFilter.java b/net/minecraft/server/network/ServerTextFilter.java
|
||||
index 5d18f6c3173ed257bef15637a53adbff26ee9062..c843e073db2a0046bbd5b64e1a4f4e956ce88a70 100644
|
||||
--- a/net/minecraft/server/network/ServerTextFilter.java
|
||||
+++ b/net/minecraft/server/network/ServerTextFilter.java
|
||||
@@ -48,7 +48,11 @@ public abstract class ServerTextFilter implements AutoCloseable {
|
||||
final ExecutorService workerPool;
|
||||
|
||||
protected static ExecutorService createWorkerPool(int size) {
|
||||
- return Executors.newFixedThreadPool(size, THREAD_FACTORY);
|
||||
+ // DivineMC start - Virtual Threads
|
||||
+ return org.bxteam.divinemc.DivineConfig.virtualThreadsEnabled && org.bxteam.divinemc.DivineConfig.virtualServerTextFilterPool
|
||||
+ ? Executors.newVirtualThreadPerTaskExecutor()
|
||||
+ : Executors.newFixedThreadPool(size, THREAD_FACTORY);
|
||||
+ // DivineMC end - Virtual Threads
|
||||
}
|
||||
|
||||
protected ServerTextFilter(
|
||||
@@ -1,87 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Mon, 3 Mar 2025 19:29:13 +0300
|
||||
Subject: [PATCH] Async Chunk Sending
|
||||
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||
index 76b8d42ae530b59cdaba0583365a557da6b90ede..235772cc9a7c878235b97c8d84cacda3016f91ca 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java
|
||||
@@ -55,6 +55,8 @@ public final class RegionizedPlayerChunkLoader {
|
||||
public static final int LOADED_TICKET_LEVEL = ChunkTaskScheduler.getTicketLevel(ChunkStatus.EMPTY);
|
||||
public static final int TICK_TICKET_LEVEL = ChunkHolderManager.ENTITY_TICKING_TICKET_LEVEL;
|
||||
|
||||
+ private static final org.apache.logging.log4j.Logger LOGGER = org.apache.logging.log4j.LogManager.getLogger("RegionizedPlayerChunkLoader"); // DivineMC - Async Chunk Sending
|
||||
+
|
||||
public static final class ViewDistanceHolder {
|
||||
|
||||
private volatile ViewDistances viewDistances;
|
||||
@@ -426,17 +428,61 @@ public final class RegionizedPlayerChunkLoader {
|
||||
}
|
||||
|
||||
private void sendChunk(final int chunkX, final int chunkZ) {
|
||||
- if (this.sentChunks.add(CoordinateUtils.getChunkKey(chunkX, chunkZ))) {
|
||||
- ((ChunkSystemChunkHolder)((ChunkSystemServerLevel)this.world).moonrise$getChunkTaskScheduler().chunkHolderManager
|
||||
- .getChunkHolder(chunkX, chunkZ).vanillaChunkHolder).moonrise$addReceivedChunk(this.player);
|
||||
+ // DivineMC start - Async Chunk Sending
|
||||
+ final long chunkKey = CoordinateUtils.getChunkKey(chunkX, chunkZ);
|
||||
+
|
||||
+ if (!this.sentChunks.add(chunkKey)) return;
|
||||
|
||||
- final LevelChunk chunk = ((ChunkSystemLevel)this.world).moonrise$getFullChunkIfLoaded(chunkX, chunkZ);
|
||||
+ final LevelChunk chunk = ((ChunkSystemLevel) this.world).moonrise$getFullChunkIfLoaded(chunkX, chunkZ);
|
||||
+ if (chunk == null) {
|
||||
+ this.sentChunks.remove(chunkKey);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
+ try {
|
||||
+ ((ChunkSystemServerLevel) this.world).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkX, chunkZ).vanillaChunkHolder.moonrise$addReceivedChunk(this.player);
|
||||
PlatformHooks.get().onChunkWatch(this.world, chunk, this.player);
|
||||
- PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
|
||||
+ } catch (IllegalStateException e) {
|
||||
+ this.sentChunks.remove(chunkKey);
|
||||
return;
|
||||
}
|
||||
- throw new IllegalStateException();
|
||||
+
|
||||
+ if (org.bxteam.divinemc.DivineConfig.asyncChunkSendingEnabled) {
|
||||
+ net.minecraft.Util.backgroundExecutor().execute(() -> {
|
||||
+ try {
|
||||
+ // Modified from PlayerChunkSender#sendChunk
|
||||
+ final net.minecraft.server.network.ServerGamePacketListenerImpl connection = this.player.connection;
|
||||
+ final ServerLevel serverLevel = this.world;
|
||||
+
|
||||
+ final net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket packet = new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
||||
+ chunk, serverLevel.getLightEngine(), null, null,
|
||||
+ serverLevel.chunkPacketBlockController.shouldModify(this.player, chunk)
|
||||
+ );
|
||||
+
|
||||
+ serverLevel.getServer().execute(() -> {
|
||||
+ if (this.removed || !this.sentChunks.contains(chunkKey)) return;
|
||||
+
|
||||
+ connection.send(packet);
|
||||
+
|
||||
+ if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
||||
+ new io.papermc.paper.event.packet.PlayerChunkLoadEvent(
|
||||
+ new org.bukkit.craftbukkit.CraftChunk(chunk),
|
||||
+ this.player.getBukkitEntity()
|
||||
+ ).callEvent();
|
||||
+ }
|
||||
+
|
||||
+ net.minecraft.network.protocol.game.DebugPackets.sendPoiPacketsForChunk(serverLevel, chunk.getPos());
|
||||
+ });
|
||||
+ } catch (Exception e) {
|
||||
+ LOGGER.error("Failed to send chunk asynchronously!", e);
|
||||
+
|
||||
+ if (!this.removed) this.sentChunks.remove(chunkKey);
|
||||
+ }
|
||||
+ });
|
||||
+ } else {
|
||||
+ PlayerChunkSender.sendChunk(this.player.connection, this.world, chunk);
|
||||
+ }
|
||||
+ // DivineMC end - Async Chunk Sending
|
||||
}
|
||||
|
||||
private void sendUnloadChunk(final int chunkX, final int chunkZ) {
|
||||
@@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Mon, 3 Mar 2025 20:08:44 +0300
|
||||
Subject: [PATCH] Option to disable disconnect.spam
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 02b4275d170cc854a7482f0e963394aee21171dd..c3e8da14d4faf560d24f877ef9eeb4a5dcb2aa8d 100644
|
||||
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -819,7 +819,7 @@ public class ServerGamePacketListenerImpl
|
||||
public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
|
||||
// PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
|
||||
// CraftBukkit start
|
||||
- if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits
|
||||
+ if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile()) && !org.bxteam.divinemc.DivineConfig.disableDisconnectSpam) { // Paper - configurable tab spam limits // DivineMC - Option to disable disconnect.spam
|
||||
this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
@@ -831,7 +831,7 @@ public class ServerGamePacketListenerImpl
|
||||
// Paper end - Don't suggest if tab-complete is disabled
|
||||
// Paper start
|
||||
final int index;
|
||||
- if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) {
|
||||
+ if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64) && !org.bxteam.divinemc.DivineConfig.disableDisconnectSpam) { // DivineMC - Option to disable disconnect.spam
|
||||
this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
@@ -891,6 +891,7 @@ public class ServerGamePacketListenerImpl
|
||||
ParseResults<CommandSourceStack> parseResults = this.server.getCommands().getDispatcher().parse(stringReader, this.player.createCommandSourceStack());
|
||||
// Paper start - Handle non-recoverable exceptions
|
||||
if (!parseResults.getExceptions().isEmpty()
|
||||
+ && !org.bxteam.divinemc.DivineConfig.disableDisconnectSpam // DivineMC - Option to disable disconnect.spam
|
||||
&& parseResults.getExceptions().values().stream().anyMatch(e -> e instanceof io.papermc.paper.brigadier.TagParseCommandSyntaxException)) {
|
||||
this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM);
|
||||
return;
|
||||
@@ -2624,6 +2625,7 @@ public class ServerGamePacketListenerImpl
|
||||
// this.chatSpamThrottler.increment();
|
||||
if (!this.chatSpamThrottler.isIncrementAndUnderThreshold()
|
||||
// CraftBukkit end
|
||||
+ && !org.bxteam.divinemc.DivineConfig.disableDisconnectSpam // DivineMC - Option to disable disconnect.spam
|
||||
&& !this.server.getPlayerList().isOp(this.player.getGameProfile())
|
||||
&& !this.server.isSingleplayerOwner(this.player.getGameProfile())) {
|
||||
this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause & add proper async disconnect
|
||||
@@ -3402,7 +3404,7 @@ public class ServerGamePacketListenerImpl
|
||||
public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {
|
||||
// Paper start - auto recipe limit
|
||||
if (!org.bukkit.Bukkit.isPrimaryThread()) {
|
||||
- if (!this.recipeSpamPackets.isIncrementAndUnderThreshold()) {
|
||||
+ if (!this.recipeSpamPackets.isIncrementAndUnderThreshold() && !org.bxteam.divinemc.DivineConfig.disableDisconnectSpam) { // DivineMC - Option to disable disconnect.spam
|
||||
this.disconnectAsync(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Wed, 5 Mar 2025 18:08:25 +0300
|
||||
Subject: [PATCH] Configurable MC-59471
|
||||
|
||||
Bring back MC-59471, MC-129055 on 1.21.2+, which fixed in 1.21.2 snapshots 24w33a and 24w36a
|
||||
|
||||
P.S: This setting is different from skip-tripwire-hook-placement-validation in Paper
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
index 9aace993c6c18f1a50610e4766225485984b8167..0849e0b116845a16792855afdd16de7ec6838542 100644
|
||||
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
@@ -201,7 +201,6 @@ public class TripWireHookBlock extends Block {
|
||||
if (!cancelledEmitterHook) { // Paper - Call BlockRedstoneEvent
|
||||
emitState(level, pos, flag2, flag3, flag, flag1);
|
||||
if (!attaching) {
|
||||
- if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.skipTripwireHookPlacementValidation || level.getBlockState(pos).is(Blocks.TRIPWIRE_HOOK)) // Paper - Validate tripwire hook placement before update
|
||||
level.setBlock(pos, blockState1.setValue(FACING, direction), 3);
|
||||
if (shouldNotifyNeighbours) {
|
||||
notifyNeighbors(block, level, pos, direction);
|
||||
@@ -214,10 +213,17 @@ public class TripWireHookBlock extends Block {
|
||||
BlockPos blockPos1 = pos.relative(direction, i2);
|
||||
BlockState blockState2 = blockStates[i2];
|
||||
if (blockState2 != null) {
|
||||
- BlockState blockState3 = level.getBlockState(blockPos1);
|
||||
- if (blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) {
|
||||
- if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(flag2)), 3); // Paper - prevent tripwire from updating
|
||||
+ // DivineMC start - Configurable MC-59471
|
||||
+ if (level.divineConfig.allowTripwireDupe) {
|
||||
+ level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, flag2), 3);
|
||||
+ level.getBlockState(blockPos1);
|
||||
+ } else {
|
||||
+ BlockState blockState3 = level.getBlockState(blockPos1);
|
||||
+ if (blockState3.is(Blocks.TRIPWIRE) || blockState3.is(Blocks.TRIPWIRE_HOOK)) {
|
||||
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates || !blockState3.is(Blocks.TRIPWIRE)) level.setBlock(blockPos1, blockState2.trySetValue(ATTACHED, Boolean.valueOf(flag2)), 3); // Paper - prevent tripwire from updating
|
||||
+ }
|
||||
}
|
||||
+ // DivineMC end - Configurable MC-59471
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 8 Mar 2025 13:27:07 +0300
|
||||
Subject: [PATCH] ModernFix: compact_bit_storage
|
||||
|
||||
This patch is based on following mixins:
|
||||
* "org/embeddedt/modernfix/common/mixin/perf/compact_bit_storage/PalettedContainerMixin.java"
|
||||
By: embeddedt <42941056+embeddedt@users.noreply.github.com>
|
||||
As part of: ModernFix (https://github.com/embeddedt/ModernFix)
|
||||
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
index 712d3d1669aecd38934957c81835e1f38289539a..810e61913aece5a8158f83b6dd56a7b6cb083c19 100644
|
||||
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
@@ -275,6 +275,28 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
data.palette.read(buffer);
|
||||
buffer.readLongArray(data.storage.getRaw());
|
||||
this.data = data;
|
||||
+ // DivineMC start - ModernFix: compact_bit_storage
|
||||
+ if (org.bxteam.divinemc.DivineConfig.useCompactBitStorage && _byte > 1) {
|
||||
+ long[] storageArray = this.data.storage.getRaw();
|
||||
+ boolean empty = true;
|
||||
+ for (long l : storageArray) {
|
||||
+ if (l != 0) {
|
||||
+ empty = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (empty && storageArray.length > 0) {
|
||||
+ T value;
|
||||
+ try {
|
||||
+ value = this.data.palette.valueFor(0);
|
||||
+ } catch (RuntimeException e) {
|
||||
+ return;
|
||||
+ }
|
||||
+ this.data = this.createOrReuseData(null, 0);
|
||||
+ this.data.palette.idFor(value);
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - ModernFix: compact_bit_storage
|
||||
this.addPresetValues(); // Paper - Anti-Xray - Add preset values (inefficient, but this isn't used by the server)
|
||||
this.updateData(this.data); // Paper - optimise palette reads
|
||||
} finally {
|
||||
@@ -1,72 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 15 Mar 2025 22:01:08 +0300
|
||||
Subject: [PATCH] Command block parse results caching
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/BaseCommandBlock.java b/net/minecraft/world/level/BaseCommandBlock.java
|
||||
index 8c883ff13866d6416bd70cc61ab1e37dd1a5b33c..7bd3507837862b8afb8227a85a44c879692a9631 100644
|
||||
--- a/net/minecraft/world/level/BaseCommandBlock.java
|
||||
+++ b/net/minecraft/world/level/BaseCommandBlock.java
|
||||
@@ -32,6 +32,10 @@ public abstract class BaseCommandBlock implements CommandSource {
|
||||
private String command = "";
|
||||
@Nullable
|
||||
private Component customName;
|
||||
+ // DivineMC start - Caching command block parse results
|
||||
+ private String lastExecutedCommand;
|
||||
+ private com.mojang.brigadier.ParseResults<CommandSourceStack> parseResultsCache;
|
||||
+ // DivineMC end - Caching command block parse results
|
||||
// CraftBukkit start
|
||||
@Override
|
||||
public abstract org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper);
|
||||
@@ -131,7 +135,35 @@ public abstract class BaseCommandBlock implements CommandSource {
|
||||
this.successCount++;
|
||||
}
|
||||
});
|
||||
- server.getCommands().dispatchServerCommand(commandSourceStack, this.command); // CraftBukkit
|
||||
+ // DivineMC start - Command block parse results caching
|
||||
+ if (org.bxteam.divinemc.DivineConfig.commandBlockParseResultsCaching) {
|
||||
+ String commandCache = this.command;
|
||||
+ // noinspection DuplicatedCode
|
||||
+ com.google.common.base.Joiner joiner = com.google.common.base.Joiner.on(" ");
|
||||
+
|
||||
+ if (commandCache.startsWith("/")) {
|
||||
+ commandCache = commandCache.substring(1);
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.server.ServerCommandEvent event = new org.bukkit.event.server.ServerCommandEvent(commandSourceStack.getBukkitSender(), commandCache);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
|
||||
+ if (!event.isCancelled()) {
|
||||
+ commandCache = event.getCommand();
|
||||
+ String[] args = commandCache.split(" ");
|
||||
+
|
||||
+ if (args.length != 0) {
|
||||
+ String newCommand = joiner.join(args);
|
||||
+ if (!newCommand.equals(lastExecutedCommand) || parseResultsCache == null) {
|
||||
+ MinecraftServer.LOGGER.info("Recompiling parse results cache for command block at ({}, {}, {})", this.getPosition().x, this.getPosition().y, this.getPosition().z);
|
||||
+ this.cache(server.getCommands().getDispatcher(), commandSourceStack, newCommand);
|
||||
+ }
|
||||
+ server.getCommands().performCommand(parseResultsCache, newCommand);
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ server.getCommands().dispatchServerCommand(commandSourceStack, this.command); // CraftBukkit
|
||||
+ }
|
||||
+ // DivineMC end - Command block parse results caching
|
||||
} catch (Throwable var6) {
|
||||
CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block");
|
||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed");
|
||||
@@ -151,6 +183,13 @@ public abstract class BaseCommandBlock implements CommandSource {
|
||||
}
|
||||
}
|
||||
|
||||
+ // DivineMC start - Command block parse results caching
|
||||
+ private void cache(com.mojang.brigadier.CommandDispatcher<CommandSourceStack> dispatcher, CommandSourceStack commandSourceStack, String commandCache) {
|
||||
+ this.parseResultsCache = dispatcher.parse(commandCache, commandSourceStack);
|
||||
+ this.lastExecutedCommand = commandCache;
|
||||
+ }
|
||||
+ // DivineMC end - Command block parse results caching
|
||||
+
|
||||
public Component getName() {
|
||||
return this.customName != null ? this.customName : DEFAULT_NAME;
|
||||
}
|
||||
@@ -1,328 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 16 Mar 2025 21:16:55 +0300
|
||||
Subject: [PATCH] Linear region file format
|
||||
|
||||
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
|
||||
index a814512fcfb85312474ae2c2c21443843bf57831..fdccc27c528b01b16a72e614ffd96523aa6f50d2 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
|
||||
@@ -8,9 +8,9 @@ public interface ChunkSystemRegionFileStorage {
|
||||
|
||||
public boolean moonrise$doesRegionFileNotExistNoIO(final int chunkX, final int chunkZ);
|
||||
|
||||
- public RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ);
|
||||
+ public org.bxteam.divinemc.region.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ); // DivineMC - Linear region file format
|
||||
|
||||
- public RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException;
|
||||
+ public org.bxteam.divinemc.region.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException; // DivineMC - Linear region file format
|
||||
|
||||
public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(
|
||||
final int chunkX, final int chunkZ, final CompoundTag compound
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
index 98fbc5c8044bd945d64569f13412a6e7e49a4e7f..34682217252cb98a70511a8cb25f077ec9f872b8 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
|
||||
@@ -1260,7 +1260,7 @@ public final class MoonriseRegionFileIO {
|
||||
this.regionDataController.finishWrite(this.chunkX, this.chunkZ, writeData);
|
||||
// Paper start - flush regionfiles on save
|
||||
if (this.world.paperConfig().chunks.flushRegionsOnSave) {
|
||||
- final RegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ);
|
||||
+ final org.bxteam.divinemc.region.IRegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ); // DivineMC - Linear region file format
|
||||
if (regionFile != null) {
|
||||
regionFile.flush();
|
||||
} // else: evicted from cache, which should have called flush
|
||||
@@ -1470,7 +1470,7 @@ public final class MoonriseRegionFileIO {
|
||||
|
||||
public static interface IORunnable {
|
||||
|
||||
- public void run(final RegionFile regionFile) throws IOException;
|
||||
+ public void run(final org.bxteam.divinemc.region.IRegionFile regionFile) throws IOException; // DivineMC - Linear region file format
|
||||
|
||||
}
|
||||
}
|
||||
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
|
||||
index 51c126735ace8fdde89ad97b5cab62f244212db0..8713d00d767c9225a0823d2fdbb0b479005738d7 100644
|
||||
--- a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
|
||||
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
|
||||
@@ -8,5 +8,5 @@ public interface ChunkSystemChunkBuffer {
|
||||
|
||||
public void moonrise$setWriteOnClose(final boolean value);
|
||||
|
||||
- public void moonrise$write(final RegionFile regionFile) throws IOException;
|
||||
+ public void moonrise$write(final org.bxteam.divinemc.region.IRegionFile regionFile) throws IOException; // DivineMC - Linear region file format
|
||||
}
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 26a4a279122bb03a83dd4a34e780d6a4567ba3a8..51b79f614417f231951e9ba05b29ff0044e081e7 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -947,10 +947,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
// CraftBukkit end
|
||||
if (flush) {
|
||||
for (ServerLevel serverLevel2 : this.getAllLevels()) {
|
||||
- LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName());
|
||||
+ LOGGER.info("ThreadedChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName()); // DivineMC - Linear region file format
|
||||
}
|
||||
|
||||
- LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved");
|
||||
+ LOGGER.info("ThreadedChunkStorage: All dimensions are saved"); // DivineMC - Linear region file format
|
||||
}
|
||||
|
||||
return flag;
|
||||
diff --git a/net/minecraft/util/worldupdate/WorldUpgrader.java b/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
index e0bcda2ddea0d6633445a7440fbf0d18e50a7653..e99f3c3567f9e6fb5a328bf9b59d40c72522f922 100644
|
||||
--- a/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
+++ b/net/minecraft/util/worldupdate/WorldUpgrader.java
|
||||
@@ -72,7 +72,7 @@ public class WorldUpgrader implements AutoCloseable {
|
||||
volatile int skipped;
|
||||
final Reference2FloatMap<ResourceKey<Level>> progressMap = Reference2FloatMaps.synchronize(new Reference2FloatOpenHashMap<>());
|
||||
volatile Component status = Component.translatable("optimizeWorld.stage.counting");
|
||||
- static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
|
||||
+ static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.(linear | mca)$"); // DivineMC - Linear region file format
|
||||
final DimensionDataStorage overworldDataStorage;
|
||||
|
||||
public WorldUpgrader(
|
||||
@@ -261,7 +261,7 @@ public class WorldUpgrader implements AutoCloseable {
|
||||
}
|
||||
|
||||
private static List<WorldUpgrader.FileToUpgrade> getAllChunkPositions(RegionStorageInfo regionStorageInfo, Path path) {
|
||||
- File[] files = path.toFile().listFiles((directory, filename) -> filename.endsWith(".mca"));
|
||||
+ File[] files = path.toFile().listFiles((directory, filename) -> filename.endsWith(".linear") || filename.endsWith(".mca")); // DivineMC - Linear region file format
|
||||
if (files == null) {
|
||||
return List.of();
|
||||
} else {
|
||||
@@ -274,7 +274,7 @@ public class WorldUpgrader implements AutoCloseable {
|
||||
int i1 = Integer.parseInt(matcher.group(2)) << 5;
|
||||
List<ChunkPos> list1 = Lists.newArrayList();
|
||||
|
||||
- try (RegionFile regionFile = new RegionFile(regionStorageInfo, file.toPath(), path, true)) {
|
||||
+ try (org.bxteam.divinemc.region.IRegionFile regionFile = org.bxteam.divinemc.region.RegionFileFactory.getAbstractRegionFile(regionStorageInfo, file.toPath(), path, true)) { // DivineMC - Linear region file format
|
||||
for (int i2 = 0; i2 < 32; i2++) {
|
||||
for (int i3 = 0; i3 < 32; i3++) {
|
||||
ChunkPos chunkPos = new ChunkPos(i2 + i, i3 + i1);
|
||||
@@ -322,7 +322,7 @@ public class WorldUpgrader implements AutoCloseable {
|
||||
|
||||
protected abstract boolean tryProcessOnePosition(T chunkStorage, ChunkPos chunkPos, ResourceKey<Level> dimension);
|
||||
|
||||
- private void onFileFinished(RegionFile regionFile) {
|
||||
+ private void onFileFinished(org.bxteam.divinemc.region.IRegionFile regionFile) { // DivineMC - Linear region file format
|
||||
if (WorldUpgrader.this.recreateRegionFiles) {
|
||||
if (this.previousWriteFuture != null) {
|
||||
this.previousWriteFuture.join();
|
||||
@@ -424,7 +424,7 @@ public class WorldUpgrader implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
- record FileToUpgrade(RegionFile file, List<ChunkPos> chunksToUpgrade) {
|
||||
+ record FileToUpgrade(org.bxteam.divinemc.region.IRegionFile file, List<ChunkPos> chunksToUpgrade) { // DivineMC - Linear region file format
|
||||
}
|
||||
|
||||
class PoiUpgrader extends WorldUpgrader.SimpleRegionStorageUpgrader {
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index c72494e757a9dc50e053dbc873f7b30e83d5cb8c..2988084cf2d72557dd304dcb904d09441e79863d 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
-public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile { // Paper - rewrite chunk system
|
||||
+public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile, org.bxteam.divinemc.region.IRegionFile { // Paper - rewrite chunk system // DivineMC - Linear region file format
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails
|
||||
private static final int SECTOR_BYTES = 4096;
|
||||
@@ -904,7 +904,7 @@ public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patche
|
||||
}
|
||||
|
||||
@Override
|
||||
- public final void moonrise$write(final RegionFile regionFile) throws IOException {
|
||||
+ public final void moonrise$write(final org.bxteam.divinemc.region.IRegionFile regionFile) throws IOException { // DivineMC - Linear region file format
|
||||
regionFile.write(this.pos, ByteBuffer.wrap(this.buf, 0, this.count));
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index 16cd10ab8de69ca3d29c84cf93715645322fd72a..9fd987078625bee796b381108ae7dbfb1f14d256 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -18,7 +18,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
|
||||
public static final String ANVIL_EXTENSION = ".mca";
|
||||
private static final int MAX_CACHE_SIZE = 256;
|
||||
- public final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>();
|
||||
+ public final Long2ObjectLinkedOpenHashMap<org.bxteam.divinemc.region.IRegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>(); // DivineMC - Linear region file format
|
||||
private final RegionStorageInfo info;
|
||||
private final Path folder;
|
||||
private final boolean sync;
|
||||
@@ -33,7 +33,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@Nullable
|
||||
public static ChunkPos getRegionFileCoordinates(Path file) {
|
||||
String fileName = file.getFileName().toString();
|
||||
- if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) {
|
||||
+ if (!fileName.startsWith("r.") || !fileName.endsWith(".mca") || !fileName.endsWith(".linear")) { // DivineMC - Linear region file format
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
private static final int MAX_NON_EXISTING_CACHE = 1024 * 4;
|
||||
private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
|
||||
private static String getRegionFileName(final int chunkX, final int chunkZ) {
|
||||
+ // DivineMC start - Linear region file format
|
||||
+ if (org.bxteam.divinemc.DivineConfig.regionFormatTypeName == org.bxteam.divinemc.region.RegionFileFormat.LINEAR) {
|
||||
+ return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + ".linear";
|
||||
+ }
|
||||
+ // DivineMC end - Linear region file format
|
||||
+
|
||||
return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + ".mca";
|
||||
}
|
||||
|
||||
@@ -93,15 +99,15 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
|
||||
@Override
|
||||
- public synchronized final RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) {
|
||||
+ public synchronized final org.bxteam.divinemc.region.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) { // DivineMC - Linear region file format
|
||||
return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT));
|
||||
}
|
||||
|
||||
@Override
|
||||
- public synchronized final RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException {
|
||||
+ public synchronized final org.bxteam.divinemc.region.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException { // DivineMC - Linear region file format
|
||||
final long key = ChunkPos.asLong(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
|
||||
|
||||
- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
|
||||
+ org.bxteam.divinemc.region.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // DivineMC - Linear region file format
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
@@ -125,7 +131,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
FileUtil.createDirectoriesSafe(this.folder);
|
||||
|
||||
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
|
||||
+ ret = org.bxteam.divinemc.region.RegionFileFactory.getAbstractRegionFile(this.info, regionPath, this.folder, this.sync); // DivineMC - Linear region file format
|
||||
|
||||
this.regionCache.putAndMoveToFirst(key, ret);
|
||||
|
||||
@@ -144,11 +150,11 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
|
||||
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
- final RegionFile regionFile = this.getRegionFile(pos);
|
||||
+ final org.bxteam.divinemc.region.IRegionFile regionFile = this.getRegionFile(pos); // DivineMC - Linear region file format
|
||||
|
||||
// note: not required to keep regionfile loaded after this call, as the write param takes a regionfile as input
|
||||
// (and, the regionfile parameter is unused for writing until the write call)
|
||||
- final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData writeData = ((ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile)regionFile).moonrise$startWrite(compound, pos);
|
||||
+ final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData writeData = regionFile.moonrise$startWrite(compound, pos); // DivineMC - Linear region file format
|
||||
|
||||
try { // Paper - implement RegionFileSizeException
|
||||
try {
|
||||
@@ -178,7 +184,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
) throws IOException {
|
||||
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
|
||||
if (writeData.result() == ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.DELETE) {
|
||||
- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
|
||||
+ final org.bxteam.divinemc.region.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // DivineMC - Linear region file format
|
||||
if (regionFile != null) {
|
||||
regionFile.clear(pos);
|
||||
} // else: didn't exist
|
||||
@@ -193,7 +199,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
public final ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.ReadData moonrise$readData(
|
||||
final int chunkX, final int chunkZ
|
||||
) throws IOException {
|
||||
- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
|
||||
+ final org.bxteam.divinemc.region.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // DivineMC - Linear region file format
|
||||
|
||||
final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ));
|
||||
|
||||
@@ -237,7 +243,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
// Paper start - rewrite chunk system
|
||||
- public RegionFile getRegionFile(ChunkPos chunkcoordintpair) throws IOException {
|
||||
+ public org.bxteam.divinemc.region.IRegionFile getRegionFile(ChunkPos chunkcoordintpair) throws IOException { // DivineMC - Linear region file format
|
||||
return this.getRegionFile(chunkcoordintpair, false);
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
@@ -249,7 +255,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
this.isChunkData = isChunkDataFolder(this.folder); // Paper - recalculate region file headers
|
||||
}
|
||||
|
||||
- @org.jetbrains.annotations.Contract("_, false -> !null") @Nullable private RegionFile getRegionFile(ChunkPos chunkPos, boolean existingOnly) throws IOException { // CraftBukkit
|
||||
+ @org.jetbrains.annotations.Contract("_, false -> !null") @Nullable private org.bxteam.divinemc.region.IRegionFile getRegionFile(ChunkPos chunkPos, boolean existingOnly) throws IOException { // CraftBukkit // DivineMC - Linear region file format
|
||||
// Paper start - rewrite chunk system
|
||||
if (existingOnly) {
|
||||
return this.moonrise$getRegionFileIfExists(chunkPos.x, chunkPos.z);
|
||||
@@ -257,7 +263,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
synchronized (this) {
|
||||
final long key = ChunkPos.asLong(chunkPos.x >> REGION_SHIFT, chunkPos.z >> REGION_SHIFT);
|
||||
|
||||
- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
|
||||
+ org.bxteam.divinemc.region.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // DivineMC - Linear region file format
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
@@ -272,7 +278,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
FileUtil.createDirectoriesSafe(this.folder);
|
||||
|
||||
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
|
||||
+ ret = org.bxteam.divinemc.region.RegionFileFactory.getAbstractRegionFile(this.info, regionPath, this.folder, this.sync); // DivineMC - Linear region file format
|
||||
|
||||
this.regionCache.putAndMoveToFirst(key, ret);
|
||||
|
||||
@@ -286,7 +292,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO DIVINEMC - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // DivineMC - Rebrand
|
||||
}
|
||||
|
||||
- private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
|
||||
+ private static CompoundTag readOversizedChunk(org.bxteam.divinemc.region.IRegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { // DivineMC - Linear region file format
|
||||
synchronized (regionfile) {
|
||||
try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
|
||||
CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
|
||||
@@ -321,7 +327,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
@Nullable
|
||||
public CompoundTag read(ChunkPos chunkPos) throws IOException {
|
||||
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
|
||||
- RegionFile regionFile = this.getRegionFile(chunkPos, true);
|
||||
+ org.bxteam.divinemc.region.IRegionFile regionFile = this.getRegionFile(chunkPos, true); // DivineMC - Linear region file format
|
||||
if (regionFile == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -360,7 +366,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
|
||||
public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException {
|
||||
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
|
||||
- RegionFile regionFile = this.getRegionFile(chunkPos, true);
|
||||
+ org.bxteam.divinemc.region.IRegionFile regionFile = this.getRegionFile(chunkPos, true); // DivineMC - Linear region file format
|
||||
if (regionFile == null) {
|
||||
return;
|
||||
}
|
||||
@@ -374,7 +380,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
}
|
||||
|
||||
public void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { // Paper - rewrite chunk system - public
|
||||
- RegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system
|
||||
+ org.bxteam.divinemc.region.IRegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system // DivineMC - Linear region file format
|
||||
// Paper start - rewrite chunk system
|
||||
if (regionFile == null) {
|
||||
// if the RegionFile doesn't exist, no point in deleting from it
|
||||
@@ -404,7 +410,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// Paper start - rewrite chunk system
|
||||
synchronized (this) {
|
||||
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
|
||||
- for (final RegionFile regionFile : this.regionCache.values()) {
|
||||
+ for (final org.bxteam.divinemc.region.IRegionFile regionFile : this.regionCache.values()) { // DivineMC - Linear region file format
|
||||
try {
|
||||
regionFile.close();
|
||||
} catch (final IOException ex) {
|
||||
@@ -420,7 +426,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
|
||||
// Paper start - rewrite chunk system
|
||||
synchronized (this) {
|
||||
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
|
||||
- for (final RegionFile regionFile : this.regionCache.values()) {
|
||||
+ for (final org.bxteam.divinemc.region.IRegionFile regionFile : this.regionCache.values()) { // DivineMC - Linear region file format
|
||||
try {
|
||||
regionFile.flush();
|
||||
} catch (final IOException ex) {
|
||||
@@ -1,203 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Wed, 19 Mar 2025 23:24:32 +0300
|
||||
Subject: [PATCH] Async mob spawning
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||
index 51b79f614417f231951e9ba05b29ff0044e081e7..dee93ae262a2a06e68dfe8ae1b7193172c436990 100644
|
||||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -291,6 +291,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
public java.util.concurrent.Semaphore serverLevelTickingSemaphore = null; // DivineMC - Parallel world ticking
|
||||
public final org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag compensation
|
||||
public final Set<net.minecraft.world.entity.Entity> entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // DivineMC - Skip EntityScheduler's executeTick checks if there isn't any tasks to be run
|
||||
+ public org.bxteam.divinemc.util.AsyncProcessor mobSpawnExecutor = new org.bxteam.divinemc.util.AsyncProcessor("mob_spawning"); // DivineMC - Async mob spawning
|
||||
|
||||
public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) {
|
||||
ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system
|
||||
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 7f982949304535376dabf42aab1848cabc8987cf..a2bb32b964d08079456d93d49f12b23f7c17a7db 100644
|
||||
--- a/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -183,6 +183,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
// Paper end - chunk tick iteration optimisations
|
||||
|
||||
+ // DivineMC start - Async mob spawning
|
||||
+ public boolean firstRunSpawnCounts = true;
|
||||
+ public final java.util.concurrent.atomic.AtomicBoolean spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false);
|
||||
+ // DivineMC end - Async mob spawning
|
||||
|
||||
public ServerChunkCache(
|
||||
ServerLevel level,
|
||||
@@ -581,6 +585,35 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
|
||||
this.broadcastChangedChunks();
|
||||
}
|
||||
+
|
||||
+ // DivineMC start - Async mob spawning
|
||||
+ if (org.bxteam.divinemc.DivineConfig.enableAsyncSpawning) {
|
||||
+ for (ServerPlayer player : this.level.players) {
|
||||
+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
|
||||
+ player.mobCounts[ii] = 0;
|
||||
+
|
||||
+ int newBackoff = player.mobBackoffCounts[ii] - 1;
|
||||
+ if (newBackoff < 0) {
|
||||
+ newBackoff = 0;
|
||||
+ }
|
||||
+ player.mobBackoffCounts[ii] = newBackoff;
|
||||
+ }
|
||||
+ }
|
||||
+ if (firstRunSpawnCounts) {
|
||||
+ firstRunSpawnCounts = false;
|
||||
+ spawnCountsReady.set(true);
|
||||
+ }
|
||||
+ if (spawnCountsReady.getAndSet(false)) {
|
||||
+ MinecraftServer.getServer().mobSpawnExecutor.submit(() -> {
|
||||
+ int mapped = distanceManager.getNaturalSpawnChunkCount();
|
||||
+ try {
|
||||
+ lastSpawnState = NaturalSpawner.createState(mapped, new ArrayList<>(level.entityTickList.entities), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap), true);
|
||||
+ } finally { }
|
||||
+ spawnCountsReady.set(true);
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Async mob spawning
|
||||
}
|
||||
|
||||
private void broadcastChangedChunks() {
|
||||
@@ -621,27 +654,31 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount();
|
||||
// Paper start - Optional per player mob spawns
|
||||
NaturalSpawner.SpawnState spawnState;
|
||||
+ // DivineMC start - Async mob spawning
|
||||
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
|
||||
- // re-set mob counts
|
||||
- for (ServerPlayer player : this.level.players) {
|
||||
- // Paper start - per player mob spawning backoff
|
||||
- for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
|
||||
- player.mobCounts[ii] = 0;
|
||||
-
|
||||
- int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
|
||||
- if (newBackoff < 0) {
|
||||
- newBackoff = 0;
|
||||
+ if (!org.bxteam.divinemc.DivineConfig.enableAsyncSpawning) {
|
||||
+ // re-set mob counts
|
||||
+ for (ServerPlayer player : this.level.players) {
|
||||
+ // Paper start - per player mob spawning backoff
|
||||
+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
|
||||
+ player.mobCounts[ii] = 0;
|
||||
+
|
||||
+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
|
||||
+ if (newBackoff < 0) {
|
||||
+ newBackoff = 0;
|
||||
+ }
|
||||
+ player.mobBackoffCounts[ii] = newBackoff;
|
||||
}
|
||||
- player.mobBackoffCounts[ii] = newBackoff;
|
||||
+ // Paper end - per player mob spawning backoff
|
||||
}
|
||||
- // Paper end - per player mob spawning backoff
|
||||
+ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap), true);
|
||||
}
|
||||
- spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
|
||||
} else {
|
||||
- spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
|
||||
+ lastSpawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap), false);
|
||||
+ spawnCountsReady.set(true);
|
||||
}
|
||||
+ // DivineMC end - Async mob spawning
|
||||
// Paper end - Optional per player mob spawns
|
||||
- this.lastSpawnState = spawnState;
|
||||
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
int _int = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
|
||||
List<MobCategory> filteredSpawningCategories;
|
||||
@@ -655,7 +692,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
}
|
||||
// Paper end - PlayerNaturallySpawnCreaturesEvent
|
||||
boolean flag = 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
|
||||
- filteredSpawningCategories = NaturalSpawner.getFilteredSpawningCategories(spawnState, this.spawnFriendlies, this.spawnEnemies, flag, this.level); // CraftBukkit
|
||||
+ filteredSpawningCategories = NaturalSpawner.getFilteredSpawningCategories(lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag, this.level); // CraftBukkit // DivineMC - Async mob spawning
|
||||
} else {
|
||||
filteredSpawningCategories = List.of();
|
||||
}
|
||||
@@ -663,8 +700,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
|
||||
for (LevelChunk levelChunk : chunks) {
|
||||
ChunkPos pos = levelChunk.getPos();
|
||||
levelChunk.incrementInhabitedTime(timeInhabited);
|
||||
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
|
||||
- NaturalSpawner.spawnForChunk(this.level, levelChunk, spawnState, filteredSpawningCategories);
|
||||
+ // DivineMC start - Async mob spawning
|
||||
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && (!org.bxteam.divinemc.DivineConfig.enableAsyncSpawning || spawnCountsReady.get()) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
|
||||
+ NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState, filteredSpawningCategories);
|
||||
+ // DivineMC end - Async mob spawning
|
||||
}
|
||||
|
||||
if (true) { // Paper - rewrite chunk system
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index d3f5242fc66529bf3137da4d505a6cf55e749e43..650dfce05bfc68d4c664471b430bd5c0f9629283 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -155,7 +155,18 @@ public final class NaturalSpawner {
|
||||
return list;
|
||||
}
|
||||
|
||||
+ private static int maxCapPerPlayer = -1; // DivineMC - Async mob spawning
|
||||
+
|
||||
public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, List<MobCategory> categories) {
|
||||
+ // DivineMC start - Async mob spawning
|
||||
+ if (maxCapPerPlayer < 0) {
|
||||
+ maxCapPerPlayer = 0;
|
||||
+ for (final MobCategory value : MobCategory.values()) {
|
||||
+ maxCapPerPlayer += value.getMaxInstancesPerChunk();
|
||||
+ }
|
||||
+ }
|
||||
+ // DivineMC end - Async mob spawning
|
||||
+
|
||||
for (MobCategory mobCategory : categories) {
|
||||
// Paper start - Optional per player mob spawns
|
||||
final boolean canSpawn;
|
||||
@@ -642,6 +653,13 @@ public final class NaturalSpawner {
|
||||
}
|
||||
|
||||
boolean canSpawnForCategoryLocal(MobCategory category, ChunkPos chunkPos) {
|
||||
+ // DivineMC start - Async mob spawning
|
||||
+ if (this.localMobCapCalculator == null) {
|
||||
+ LOGGER.warn("Local mob cap calculator was null! Report to DivineMC!");
|
||||
+ return false;
|
||||
+ }
|
||||
+ // DivineMC end - Async mob spawning
|
||||
+
|
||||
return this.localMobCapCalculator.canSpawn(category, chunkPos);
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/level/entity/EntityTickList.java b/net/minecraft/world/level/entity/EntityTickList.java
|
||||
index 018a04674897cfcec0e8de5cb2ab06243a994ae3..8c1de4654a3a29e75716a03efd476b8a3b7fe9e9 100644
|
||||
--- a/net/minecraft/world/level/entity/EntityTickList.java
|
||||
+++ b/net/minecraft/world/level/entity/EntityTickList.java
|
||||
@@ -9,7 +9,7 @@ import javax.annotation.Nullable;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
public class EntityTickList {
|
||||
- public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<net.minecraft.world.entity.Entity> entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system
|
||||
+ public final java.util.concurrent.ConcurrentLinkedQueue<Entity> entities = new java.util.concurrent.ConcurrentLinkedQueue<>(); // Paper - rewrite chunk system // DivineMC - Async mob spawning
|
||||
// DivineMC start - Parallel world ticking
|
||||
private final net.minecraft.server.level.ServerLevel serverLevel;
|
||||
|
||||
@@ -43,13 +43,13 @@ public class EntityTickList {
|
||||
// Paper start - rewrite chunk system
|
||||
// To ensure nothing weird happens with dimension travelling, do not iterate over new entries...
|
||||
// (by dfl iterator() is configured to not iterate over new entries)
|
||||
- final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator<Entity> iterator = this.entities.iterator();
|
||||
+ final java.util.Iterator<Entity> iterator = this.entities.iterator(); // DivineMC - Async mob spawning
|
||||
try {
|
||||
while (iterator.hasNext()) {
|
||||
entity.accept(iterator.next());
|
||||
}
|
||||
} finally {
|
||||
- iterator.finishedIterating();
|
||||
+ //iterator.finishedIterating(); // DivineMC - Async mob spawning
|
||||
}
|
||||
// Paper end - rewrite chunk system
|
||||
}
|
||||
@@ -1,437 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 23 Mar 2025 01:16:35 +0300
|
||||
Subject: [PATCH] Dynamic Activation of Brain
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
index ae0a3c3d9d6300293a6d0dff5cae49ebe7c11dab..3b08dad7a9fac7ac9acec0bfb85d4826452bdc99 100644
|
||||
--- a/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
|
||||
@@ -161,6 +161,21 @@ public final class ActivationRange {
|
||||
}
|
||||
|
||||
ActivationRange.activateEntity(entity);
|
||||
+
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (org.bxteam.divinemc.DivineConfig.dabEnabled && entity.getType().dabEnabled && (!org.bxteam.divinemc.DivineConfig.dabDontEnableIfInWater || entity.getType().is(net.minecraft.tags.EntityTypeTags.CAN_BREATHE_UNDER_WATER) || !entity.isInWaterOrBubble())) {
|
||||
+ if (!entity.activatedPriorityReset) {
|
||||
+ entity.activatedPriorityReset = true;
|
||||
+ entity.activatedPriority = org.bxteam.divinemc.DivineConfig.dabMaximumActivationFrequency;
|
||||
+ }
|
||||
+ int squaredDistance = (int) player.distanceToSqr(entity);
|
||||
+ entity.activatedPriority = squaredDistance > org.bxteam.divinemc.DivineConfig.dabStartDistanceSquared ?
|
||||
+ Math.max(1, Math.min(squaredDistance >> org.bxteam.divinemc.DivineConfig.dabActivationDistanceMod, entity.activatedPriority)) :
|
||||
+ 1;
|
||||
+ } else {
|
||||
+ entity.activatedPriority = 1;
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 561066a2cf769e13ef3cea0881f7a2010ecbf2ec..5fe908ce51f95e1eab024dcd41ed108373f17fea 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -818,6 +818,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
this.entityTickList
|
||||
.forEach(
|
||||
entity -> {
|
||||
+ entity.activatedPriorityReset = false; // DivineMC - Dynamic Activation of Brain
|
||||
if (!entity.isRemoved()) {
|
||||
if (!tickRateManager.isEntityFrozen(entity)) {
|
||||
entity.checkDespawn();
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 04ae7636d14a40a427b5d9b746632b0c489efa21..f1cd66d7d96771bc4967e214f70c756fec30efe5 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -336,6 +336,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
public boolean fixedPose = false; // Paper - Expand Pose API
|
||||
private final int despawnTime; // Paper - entity despawn time limit
|
||||
public int totalEntityAge; // Paper - age-like counter for all entities
|
||||
+ public boolean activatedPriorityReset = false; // DivineMC - Dynamic Activation of Brain
|
||||
+ public int activatedPriority = org.bxteam.divinemc.DivineConfig.dabMaximumActivationFrequency; // DivineMC - Dynamic Activation of Brain
|
||||
public final io.papermc.paper.entity.activation.ActivationType activationType = io.papermc.paper.entity.activation.ActivationType.activationTypeFor(this); // Paper - EAR 2/tracking ranges
|
||||
// Paper start - EAR 2
|
||||
public final boolean defaultActivationState;
|
||||
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
|
||||
index 4186db5cb8d2cd29ebc230d704dd125ae0dfa358..79593dc0e42e4cf0aee5e7b8cac4aca186887d6f 100644
|
||||
--- a/net/minecraft/world/entity/EntityType.java
|
||||
+++ b/net/minecraft/world/entity/EntityType.java
|
||||
@@ -1063,6 +1063,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
|
||||
private final boolean canSpawnFarFromPlayer;
|
||||
private final int clientTrackingRange;
|
||||
private final int updateInterval;
|
||||
+ public boolean dabEnabled = false; // DivineMC - Dynamic Activation of Brain
|
||||
private final String descriptionId;
|
||||
@Nullable
|
||||
private Component description;
|
||||
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
|
||||
index b4e19cc65701d5ef94e1cc0a7473225c222725c3..00daf8de01bf23f55ba8af12d3e3e551d981c61c 100644
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -218,10 +218,10 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
@Override
|
||||
public void inactiveTick() {
|
||||
super.inactiveTick();
|
||||
- if (this.goalSelector.inactiveTick()) {
|
||||
+ if (this.goalSelector.inactiveTick(this.activatedPriority, true)) { // DivineMC - Dynamic Activation of Brain
|
||||
this.goalSelector.tick();
|
||||
}
|
||||
- if (this.targetSelector.inactiveTick()) {
|
||||
+ if (this.targetSelector.inactiveTick(this.activatedPriority, true)) { // DivineMC - Dynamic Activation of Brain
|
||||
this.targetSelector.tick();
|
||||
}
|
||||
}
|
||||
@@ -888,13 +888,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
|
||||
// Paper end - Allow nerfed mobs to jump and float
|
||||
this.sensing.tick();
|
||||
int i = this.tickCount + this.getId();
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
if (i % 2 != 0 && this.tickCount > 1) {
|
||||
- this.targetSelector.tickRunningGoals(false);
|
||||
- this.goalSelector.tickRunningGoals(false);
|
||||
+ if (this.targetSelector.inactiveTick(this.activatedPriority, false))
|
||||
+ this.targetSelector.tickRunningGoals(false);
|
||||
+ if (this.goalSelector.inactiveTick(this.activatedPriority, false))
|
||||
+ this.goalSelector.tickRunningGoals(false);
|
||||
} else {
|
||||
- this.targetSelector.tick();
|
||||
- this.goalSelector.tick();
|
||||
+ if (this.targetSelector.inactiveTick(this.activatedPriority, false))
|
||||
+ this.targetSelector.tick();
|
||||
+ if (this.goalSelector.inactiveTick(this.activatedPriority, false))
|
||||
+ this.goalSelector.tick();
|
||||
}
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
|
||||
this.navigation.tick();
|
||||
this.customServerAiStep((ServerLevel)this.level());
|
||||
diff --git a/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java b/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java
|
||||
index f6c673b1abe53afcb14fd68d590431027ed29f67..1e5312e02298c63c168526a960d688dc03581cee 100644
|
||||
--- a/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java
|
||||
+++ b/net/minecraft/world/entity/ai/behavior/VillagerPanicTrigger.java
|
||||
@@ -36,7 +36,11 @@ public class VillagerPanicTrigger extends Behavior<Villager> {
|
||||
|
||||
@Override
|
||||
protected void tick(ServerLevel level, Villager owner, long gameTime) {
|
||||
- if (gameTime % 100L == 0L) {
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (owner.nextGolemPanic < 0) owner.nextGolemPanic = gameTime + 100;
|
||||
+ if (--owner.nextGolemPanic < gameTime) {
|
||||
+ owner.nextGolemPanic = -1;
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
owner.spawnGolemIfNeeded(level, gameTime, 3);
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
index b816b2de8eb327060ca6ea7c4afc17373fa77ff6..4eed0bd3670fdcb0a156c29e7db63233a47f539b 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
||||
@@ -36,10 +36,14 @@ public class GoalSelector {
|
||||
}
|
||||
|
||||
// Paper start - EAR 2
|
||||
- public boolean inactiveTick() {
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ public boolean inactiveTick(int tickRate, boolean inactive) {
|
||||
+ if (inactive && !org.bxteam.divinemc.DivineConfig.dabEnabled) tickRate = 4;
|
||||
+ tickRate = Math.min(tickRate, 3);
|
||||
this.curRate++;
|
||||
- return this.curRate % 3 == 0; // TODO newGoalRate was already unused in 1.20.4, check if this is correct
|
||||
+ return this.curRate % tickRate == 0;
|
||||
}
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
|
||||
public boolean hasTasks() {
|
||||
for (WrappedGoal task : this.availableGoals) {
|
||||
diff --git a/net/minecraft/world/entity/animal/allay/Allay.java b/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
index b2c9da89ae6044536f4996fdbd37e2cabf22ca12..fa9672e890f327dbdec57eadc258bbae8e98e91e 100644
|
||||
--- a/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
+++ b/net/minecraft/world/entity/animal/allay/Allay.java
|
||||
@@ -118,6 +118,7 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
||||
private float spinningAnimationTicks0;
|
||||
public boolean forceDancing = false; // CraftBukkit
|
||||
private org.purpurmc.purpur.controller.FlyingMoveControllerWASD purpurController; // Purpur - Ridables
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Allay(EntityType<? extends Allay> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -287,9 +288,13 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- AllayAi.updateActivity(this);
|
||||
- super.customServerAiStep(level);
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ AllayAi.updateActivity(this);
|
||||
+ super.customServerAiStep(level);
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/animal/axolotl/Axolotl.java b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
index bbfe48fd278cda9926793d0d2de743558fefd622..3f7c48282577a2de20e78b69ddcbc08347318fd3 100644
|
||||
--- a/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
+++ b/net/minecraft/world/entity/animal/axolotl/Axolotl.java
|
||||
@@ -105,6 +105,7 @@ public class Axolotl extends Animal implements VariantHolder<Axolotl.Variant>, B
|
||||
public final BinaryAnimator onGroundAnimator = new BinaryAnimator(10, Mth::easeInOutSine);
|
||||
public final BinaryAnimator movingAnimator = new BinaryAnimator(10, Mth::easeInOutSine);
|
||||
private static final int REGEN_BUFF_BASE_DURATION = 100;
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Axolotl(EntityType<? extends Axolotl> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -347,12 +348,16 @@ public class Axolotl extends Animal implements VariantHolder<Axolotl.Variant>, B
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- AxolotlAi.updateActivity(this);
|
||||
- if (!this.isNoAi()) {
|
||||
- Optional<Integer> memory = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS);
|
||||
- this.setPlayingDead(memory.isPresent() && memory.get() > 0);
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ AxolotlAi.updateActivity(this);
|
||||
+ if (!this.isNoAi()) {
|
||||
+ Optional<Integer> memory = this.getBrain().getMemory(MemoryModuleType.PLAY_DEAD_TICKS);
|
||||
+ this.setPlayingDead(memory.isPresent() && memory.get() > 0);
|
||||
+ }
|
||||
}
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
diff --git a/net/minecraft/world/entity/animal/frog/Frog.java b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
index dfcba5c2c8a489ebe74c2d5c1fa980c401806757..1827dead0a0a1d8e9dfbcc44038c9dbfbefddd48 100644
|
||||
--- a/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/Frog.java
|
||||
@@ -106,6 +106,7 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
||||
public final AnimationState swimIdleAnimationState = new AnimationState();
|
||||
private org.purpurmc.purpur.controller.MoveControllerWASD purpurLandController; // Purpur - Ridables
|
||||
private org.purpurmc.purpur.controller.WaterMoveControllerWASD purpurWaterController; // Purpur - Ridables
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Frog(EntityType<? extends Animal> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -242,9 +243,13 @@ public class Frog extends Animal implements VariantHolder<Holder<FrogVariant>> {
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- FrogAi.updateActivity(this);
|
||||
- super.customServerAiStep(level);
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ FrogAi.updateActivity(this);
|
||||
+ super.customServerAiStep(level);
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java
|
||||
index 78d256f6a95acb367efd690bc368d2106a928b8f..b32fabed65f929cb8d2c8c93667f2e45b9bef0b8 100644
|
||||
--- a/net/minecraft/world/entity/animal/frog/Tadpole.java
|
||||
+++ b/net/minecraft/world/entity/animal/frog/Tadpole.java
|
||||
@@ -62,6 +62,7 @@ public class Tadpole extends AbstractFish {
|
||||
);
|
||||
public boolean ageLocked; // Paper
|
||||
private org.purpurmc.purpur.controller.WaterMoveControllerWASD purpurController; // Purpur - Ridables
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Tadpole(EntityType<? extends AbstractFish> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -133,9 +134,13 @@ public class Tadpole extends AbstractFish {
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- TadpoleAi.updateActivity(this);
|
||||
- super.customServerAiStep(level);
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ TadpoleAi.updateActivity(this);
|
||||
+ super.customServerAiStep(level);
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
index e21f024d0ed7f936ff17df16bd9666fffbf44a75..1f46d9e9def33458001c4c30bf2e37486646d23f 100644
|
||||
--- a/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
+++ b/net/minecraft/world/entity/animal/goat/Goat.java
|
||||
@@ -90,6 +90,7 @@ public class Goat extends Animal {
|
||||
public static final EntityDataAccessor<Boolean> DATA_HAS_RIGHT_HORN = SynchedEntityData.defineId(Goat.class, EntityDataSerializers.BOOLEAN);
|
||||
private boolean isLoweringHead;
|
||||
private int lowerHeadTick;
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Goat(EntityType<? extends Goat> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -230,9 +231,13 @@ public class Goat extends Animal {
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- GoatAi.updateActivity(this);
|
||||
- super.customServerAiStep(level);
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ GoatAi.updateActivity(this);
|
||||
+ super.customServerAiStep(level);
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/hoglin/Hoglin.java b/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
index a5ee49e35b0825c03af058347ee189a7962e8027..4a02ff2dbea64cf6fb867872c08ad1b80fc5145b 100644
|
||||
--- a/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/hoglin/Hoglin.java
|
||||
@@ -84,6 +84,7 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
||||
MemoryModuleType.PACIFIED,
|
||||
MemoryModuleType.IS_PANICKING
|
||||
);
|
||||
+ private int behaviorTick; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Hoglin(EntityType<? extends Hoglin> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -203,17 +204,21 @@ public class Hoglin extends Animal implements Enemy, HoglinBase {
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- HoglinAi.updateActivity(this);
|
||||
- if (this.isConverting()) {
|
||||
- this.timeInOverworld++;
|
||||
- if (this.timeInOverworld > 300) {
|
||||
- this.makeSound(SoundEvents.HOGLIN_CONVERTED_TO_ZOMBIFIED);
|
||||
- this.finishConversion();
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ HoglinAi.updateActivity(this);
|
||||
+ if (this.isConverting()) {
|
||||
+ this.timeInOverworld++;
|
||||
+ if (this.timeInOverworld > 300) {
|
||||
+ this.makeSound(SoundEvents.HOGLIN_CONVERTED_TO_ZOMBIFIED);
|
||||
+ this.finishConversion();
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.timeInOverworld = 0;
|
||||
}
|
||||
- } else {
|
||||
- this.timeInOverworld = 0;
|
||||
}
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/piglin/Piglin.java b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||
index b2e64c0d4c1943f8a50a03ba59318fc2e6b9e26a..a7f2c0aec77a8b196c9207b071ac904c30f34ee6 100644
|
||||
--- a/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/piglin/Piglin.java
|
||||
@@ -143,6 +143,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
||||
public Set<Item> allowedBarterItems = new HashSet<>();
|
||||
public Set<Item> interestItems = new HashSet<>();
|
||||
// CraftBukkit end
|
||||
+ private int behaviorTick; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Piglin(EntityType<? extends AbstractPiglin> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -382,9 +383,13 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
//if ((getRider() == null || !this.isControllable()) && this.behaviorTick++ % this.activatedPriority == 0) // Pufferfish // Purpur - only use brain if no rider
|
||||
- this.getBrain().tick(level, this);
|
||||
- PiglinAi.updateActivity(this);
|
||||
- super.customServerAiStep(level);
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ PiglinAi.updateActivity(this);
|
||||
+ super.customServerAiStep(level);
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/warden/Warden.java b/net/minecraft/world/entity/monster/warden/Warden.java
|
||||
index 59a12809e5c7f5ee85ca1f587f6b77383a1ff062..9777f5e99909790b49b05ea64fe12dedaaba6a0a 100644
|
||||
--- a/net/minecraft/world/entity/monster/warden/Warden.java
|
||||
+++ b/net/minecraft/world/entity/monster/warden/Warden.java
|
||||
@@ -113,6 +113,7 @@ public class Warden extends Monster implements VibrationSystem {
|
||||
private final VibrationSystem.User vibrationUser;
|
||||
private VibrationSystem.Data vibrationData;
|
||||
AngerManagement angerManagement = new AngerManagement(this::canTargetEntity, Collections.emptyList());
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Warden(EntityType<? extends Monster> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -306,18 +307,22 @@ public class Warden extends Monster implements VibrationSystem {
|
||||
|
||||
@Override
|
||||
protected void customServerAiStep(ServerLevel level) {
|
||||
- this.getBrain().tick(level, this);
|
||||
- super.customServerAiStep(level);
|
||||
- if ((this.tickCount + this.getId()) % 120 == 0) {
|
||||
- applyDarknessAround(level, this.position(), this, 20);
|
||||
- }
|
||||
+ // DivineMC start - Dynamic Activation of Brain
|
||||
+ if (this.behaviorTick++ % this.activatedPriority == 0) {
|
||||
+ this.getBrain().tick(level, this);
|
||||
+ super.customServerAiStep(level);
|
||||
+ if ((this.tickCount + this.getId()) % 120 == 0) {
|
||||
+ applyDarknessAround(level, this.position(), this, 20);
|
||||
+ }
|
||||
|
||||
- if (this.tickCount % 20 == 0) {
|
||||
- this.angerManagement.tick(level, this::canTargetEntity);
|
||||
- this.syncClientAngerLevel();
|
||||
- }
|
||||
+ if (this.tickCount % 20 == 0) {
|
||||
+ this.angerManagement.tick(level, this::canTargetEntity);
|
||||
+ this.syncClientAngerLevel();
|
||||
+ }
|
||||
|
||||
- WardenAi.updateActivity(this);
|
||||
+ WardenAi.updateActivity(this);
|
||||
+ }
|
||||
+ // DivineMC end - Dynamic Activation of Brain
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
||||
index fec90e482c8935dfca609bbf90e67f86a1586221..2ac8a11e9afc6f776eba3dbe852d7b680ed21705 100644
|
||||
--- a/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -179,6 +179,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
);
|
||||
private boolean isLobotomized = false; public boolean isLobotomized() { return this.isLobotomized; } // Purpur - Lobotomize stuck villagers
|
||||
private int notLobotomizedCount = 0; // Purpur - Lobotomize stuck villagers
|
||||
+ public long nextGolemPanic = -1; // DivineMC - Dynamic Activation of Brain
|
||||
+ private int behaviorTick = 0; // DivineMC - Dynamic Activation of Brain
|
||||
|
||||
public Villager(EntityType<? extends Villager> entityType, Level level) {
|
||||
this(entityType, level, VillagerType.PLAINS);
|
||||
@@ -397,7 +399,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
}
|
||||
// Purpur end - Lobotomize stuck villagers
|
||||
// Pufferfish start
|
||||
- if (!inactive && (getRider() == null || !this.isControllable()) /*&& this.behaviorTick++ % this.activatedPriority == 0*/) { // Purpur - Ridables
|
||||
+ if (!inactive && this.behaviorTick++ % this.activatedPriority == 0 && (getRider() == null || !this.isControllable()) /*&& this.behaviorTick++ % this.activatedPriority == 0*/) { // Purpur - Ridables // DivineMC - Dynamic Activation of Brain
|
||||
this.getBrain().tick(level, this); // Paper - EAR 2
|
||||
}
|
||||
else if (this.isLobotomized && shouldRestock()) restock(); // Purpur - Lobotomize stuck villagers
|
||||
@@ -1,82 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 23 Mar 2025 01:26:54 +0300
|
||||
Subject: [PATCH] Configurable movement speed for entities
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/entity/monster/Drowned.java b/net/minecraft/world/entity/monster/Drowned.java
|
||||
index 2686df57d9d48db1438278d0d053bdbd3c65c0a7..44fa660cbe277c2b2dd5cce3e508b61848b2cccc 100644
|
||||
--- a/net/minecraft/world/entity/monster/Drowned.java
|
||||
+++ b/net/minecraft/world/entity/monster/Drowned.java
|
||||
@@ -97,6 +97,7 @@ public class Drowned extends Zombie implements RangedAttackMob {
|
||||
public void initAttributes() {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.drownedMaxHealth);
|
||||
this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.drownedScale);
|
||||
+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.drownedMovementSpeed); // DivineMC - Configurable movement speed for entities
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/Husk.java b/net/minecraft/world/entity/monster/Husk.java
|
||||
index a5bfc6f5caba1da8cfcb345524e05e8676672cb0..02ba60f5624c99c6360fa5f08aa2d518e34772ab 100644
|
||||
--- a/net/minecraft/world/entity/monster/Husk.java
|
||||
+++ b/net/minecraft/world/entity/monster/Husk.java
|
||||
@@ -43,6 +43,7 @@ public class Husk extends Zombie {
|
||||
@Override
|
||||
public void initAttributes() {
|
||||
this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.huskMaxHealth);
|
||||
+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.huskMovementSpeed); // DivineMC - Configurable movement speed for entities
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 7af71c777dca26cd94b1807a2a77ea0d30e92976..5a86d217f9f8374c4ca8846fa22e721ad1f3f11b 100644
|
||||
--- a/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -123,6 +123,7 @@ public class Zombie extends Monster {
|
||||
public void initAttributes() {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombieMaxHealth);
|
||||
this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zombieScale);
|
||||
+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.zombieMovementSpeed); // DivineMC - Configurable movement speed for entities
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
@@ -190,7 +191,6 @@ public class Zombie extends Monster {
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return Monster.createMonsterAttributes()
|
||||
.add(Attributes.FOLLOW_RANGE, 35.0)
|
||||
- .add(Attributes.MOVEMENT_SPEED, 0.23F)
|
||||
.add(Attributes.ATTACK_DAMAGE, 3.0)
|
||||
.add(Attributes.ARMOR, 2.0)
|
||||
.add(Attributes.SPAWN_REINFORCEMENTS_CHANCE);
|
||||
diff --git a/net/minecraft/world/entity/monster/ZombieVillager.java b/net/minecraft/world/entity/monster/ZombieVillager.java
|
||||
index 2d5ddf98b79f97bdd15593a5989f978155375e99..a053f42a1ffa7285ddf18f3f92dea803f4fe9461 100644
|
||||
--- a/net/minecraft/world/entity/monster/ZombieVillager.java
|
||||
+++ b/net/minecraft/world/entity/monster/ZombieVillager.java
|
||||
@@ -99,6 +99,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
|
||||
@Override
|
||||
public void initAttributes() {
|
||||
this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombieVillagerMaxHealth);
|
||||
+ this.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.zombieVillagerMovementSpeed); // DivineMC - Configurable movement speed for entities
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
||||
index fddbbffafea275dad187b7908386cf4c05c86743..05256fefd6b015d84adadd877110440ac31a48b4 100644
|
||||
--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
||||
+++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java
|
||||
@@ -85,6 +85,7 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
|
||||
public void initAttributes() {
|
||||
this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level().purpurConfig.zombifiedPiglinMaxHealth);
|
||||
this.getAttribute(Attributes.SCALE).setBaseValue(this.level().purpurConfig.zombifiedPiglinScale);
|
||||
+ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level().purpurConfig.zombifiedPiglinMovementSpeed); // DivineMC - Configurable movement speed for entities
|
||||
}
|
||||
// Purpur end - Configurable entity base attributes
|
||||
|
||||
@@ -136,7 +137,6 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob {
|
||||
public static AttributeSupplier.Builder createAttributes() {
|
||||
return Zombie.createAttributes()
|
||||
.add(Attributes.SPAWN_REINFORCEMENTS_CHANCE, 0.0)
|
||||
- .add(Attributes.MOVEMENT_SPEED, 0.23F)
|
||||
.add(Attributes.ATTACK_DAMAGE, 5.0);
|
||||
}
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 23 Mar 2025 16:47:24 +0300
|
||||
Subject: [PATCH] Paper PR: Add FillBottleEvents for player and dispenser
|
||||
|
||||
|
||||
diff --git a/net/minecraft/core/cauldron/CauldronInteraction.java b/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
index b402f6a6ecb8047bbb791b212fba375f4c9e6af5..f381f3ecd27315e06ca6883006a8a4c3eb443c34 100644
|
||||
--- a/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
+++ b/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
@@ -63,7 +63,12 @@ public interface CauldronInteraction {
|
||||
}
|
||||
// CraftBukkit end
|
||||
Item item = stack.getItem();
|
||||
- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ final io.papermc.paper.event.player.PlayerFillBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerFillBottleEvent(player, hand, stack, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.GLASS_BOTTLE)));
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
player.awardStat(Stats.USE_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(item));
|
||||
// level.setBlockAndUpdate(pos, Blocks.WATER_CAULDRON.defaultBlockState()); // CraftBukkit
|
||||
diff --git a/net/minecraft/core/dispenser/DispenseItemBehavior.java b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
index c8c8351f5645cf4041d26b0e02c072546ad329c6..75a695aaf0dd2f58e1fa5e1c532ae298c2a2abdb 100644
|
||||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -727,13 +727,25 @@ public interface DispenseItemBehavior {
|
||||
blockStateBase -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL) && blockStateBase.getBlock() instanceof BeehiveBlock
|
||||
)
|
||||
&& blockState.getValue(BeehiveBlock.HONEY_LEVEL) >= 5) {
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ final io.papermc.paper.event.block.BlockFillBottleEvent bottleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFillBottleEvent(serverLevel, blockSource.pos(), item, new ItemStack(Items.HONEY_BOTTLE));
|
||||
+ if (bottleEvent.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
((BeehiveBlock)blockState.getBlock())
|
||||
.releaseBeesAndResetHoneyLevel(serverLevel, blockState, blockPos, null, BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED);
|
||||
this.setSuccess(true);
|
||||
- return this.takeLiquid(blockSource, item, new ItemStack(Items.HONEY_BOTTLE));
|
||||
+ return this.takeLiquid(blockSource, item, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bottleEvent.getResultItem())); // DivineMC - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
} else if (serverLevel.getFluidState(blockPos).is(FluidTags.WATER)) {
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ final io.papermc.paper.event.block.BlockFillBottleEvent bottleEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFillBottleEvent(serverLevel, blockSource.pos(), item, PotionContents.createItemStack(Items.POTION, Potions.WATER));
|
||||
+ if (bottleEvent.isCancelled()) {
|
||||
+ return item;
|
||||
+ }
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
this.setSuccess(true);
|
||||
- return this.takeLiquid(blockSource, item, PotionContents.createItemStack(Items.POTION, Potions.WATER));
|
||||
+ return this.takeLiquid(blockSource, item, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(bottleEvent.getResultItem())); // DivineMC - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
} else {
|
||||
return super.execute(blockSource, item);
|
||||
}
|
||||
diff --git a/net/minecraft/world/item/BottleItem.java b/net/minecraft/world/item/BottleItem.java
|
||||
index 105f9166297de2bfa6bdcfa9f6a0ffb00c0242ac..111f43fc5c74577f8f3067a4f84be7a6f96fdfb2 100644
|
||||
--- a/net/minecraft/world/item/BottleItem.java
|
||||
+++ b/net/minecraft/world/item/BottleItem.java
|
||||
@@ -35,6 +35,18 @@ public class BottleItem extends Item {
|
||||
);
|
||||
ItemStack itemInHand = player.getItemInHand(hand);
|
||||
if (!entitiesOfClass.isEmpty()) {
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ final io.papermc.paper.event.player.PlayerFillBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerFillBottleEvent(player, hand, itemInHand, new ItemStack(Items.DRAGON_BREATH));
|
||||
+ //noinspection DuplicatedCode
|
||||
+ if (event.isCancelled()) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ final ItemStack resultItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getResultItem());
|
||||
+ if (resultItem.is(itemInHand.getItem())) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ }
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
AreaEffectCloud areaEffectCloud = entitiesOfClass.get(0);
|
||||
areaEffectCloud.setRadius(areaEffectCloud.getRadius() - 0.5F);
|
||||
level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL_DRAGONBREATH, SoundSource.NEUTRAL, 1.0F, 1.0F);
|
||||
@@ -43,7 +55,7 @@ public class BottleItem extends Item {
|
||||
CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(serverPlayer, itemInHand, areaEffectCloud);
|
||||
}
|
||||
|
||||
- return InteractionResult.SUCCESS.heldItemTransformedTo(this.turnBottleIntoItem(itemInHand, player, new ItemStack(Items.DRAGON_BREATH)));
|
||||
+ return InteractionResult.SUCCESS.heldItemTransformedTo(this.turnBottleIntoItem(itemInHand, player, resultItem)); // DivineMC - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
} else {
|
||||
BlockHitResult playerPovHitResult = getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY);
|
||||
if (playerPovHitResult.getType() == HitResult.Type.MISS) {
|
||||
@@ -56,10 +68,22 @@ public class BottleItem extends Item {
|
||||
}
|
||||
|
||||
if (level.getFluidState(blockPos).is(FluidTags.WATER)) {
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ final io.papermc.paper.event.player.PlayerFillBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerFillBottleEvent(player, hand, itemInHand, PotionContents.createItemStack(Items.POTION, Potions.WATER));
|
||||
+ //noinspection DuplicatedCode
|
||||
+ if (event.isCancelled()) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ final ItemStack resultItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getResultItem());
|
||||
+ if (resultItem.is(itemInHand.getItem())) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ }
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
|
||||
level.gameEvent(player, GameEvent.FLUID_PICKUP, blockPos);
|
||||
return InteractionResult.SUCCESS
|
||||
- .heldItemTransformedTo(this.turnBottleIntoItem(itemInHand, player, PotionContents.createItemStack(Items.POTION, Potions.WATER)));
|
||||
+ .heldItemTransformedTo(this.turnBottleIntoItem(itemInHand, player, resultItem)); // DivineMC - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/BeehiveBlock.java b/net/minecraft/world/level/block/BeehiveBlock.java
|
||||
index fd49500f735e3482a0118316bd7a4340f41fe8be..4160c0649be830476b5bbea97557d9a505672abc 100644
|
||||
--- a/net/minecraft/world/level/block/BeehiveBlock.java
|
||||
+++ b/net/minecraft/world/level/block/BeehiveBlock.java
|
||||
@@ -158,12 +158,26 @@ public class BeehiveBlock extends BaseEntityBlock {
|
||||
flag = true;
|
||||
level.gameEvent(player, GameEvent.SHEAR, pos);
|
||||
} else if (stack.is(Items.GLASS_BOTTLE)) {
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ final io.papermc.paper.event.player.PlayerFillBottleEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerFillBottleEvent(player, hand, stack, new ItemStack(Items.HONEY_BOTTLE));
|
||||
+ //noinspection DuplicatedCode
|
||||
+ if (event.isCancelled()) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ final ItemStack resultItem = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getResultItem());
|
||||
+ if (resultItem.is(stack.getItem())) {
|
||||
+ player.containerMenu.sendAllDataToRemote();
|
||||
+ }
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
stack.shrink(1);
|
||||
level.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
if (stack.isEmpty()) {
|
||||
- player.setItemInHand(hand, new ItemStack(Items.HONEY_BOTTLE));
|
||||
- } else if (!player.getInventory().add(new ItemStack(Items.HONEY_BOTTLE))) {
|
||||
- player.drop(new ItemStack(Items.HONEY_BOTTLE), false);
|
||||
+ // DivineMC start - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
+ player.setItemInHand(hand, resultItem);
|
||||
+ } else if (!player.getInventory().add(resultItem)) {
|
||||
+ player.drop(resultItem, false);
|
||||
+ // DivineMC end - Paper PR: Add FillBottleEvents for player and dispenser
|
||||
}
|
||||
|
||||
flag = true;
|
||||
@@ -1,50 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Wed, 26 Mar 2025 01:46:49 +0300
|
||||
Subject: [PATCH] Leaf: Improve BlockEntity ticking isRemoved check
|
||||
|
||||
|
||||
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 0337f4b9ca3c9c9a1e2a7cf19fcbad5e78b949dc..1820069a7c5833b0a13e034c232f06af234788e3 100644
|
||||
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -989,13 +989,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
|
||||
public static class RebindableTickingBlockEntityWrapper implements TickingBlockEntity {
|
||||
public TickingBlockEntity ticker;
|
||||
+ private @Nullable BlockEntity blockEntityReference = null; // DivineMC - Improve BlockEntity ticking isRemoved check
|
||||
|
||||
RebindableTickingBlockEntityWrapper(TickingBlockEntity ticker) {
|
||||
this.ticker = ticker;
|
||||
+ // DivineMC start - Improve BlockEntity ticking isRemoved check
|
||||
+ if (ticker instanceof BoundTickingBlockEntity<?> boundTicker) {
|
||||
+ blockEntityReference = boundTicker.blockEntity;
|
||||
+ }
|
||||
+ // DivineMC end - Improve BlockEntity ticking isRemoved check
|
||||
}
|
||||
|
||||
public void rebind(TickingBlockEntity ticker) {
|
||||
this.ticker = ticker;
|
||||
+ // DivineMC start - Improve BlockEntity ticking isRemoved check
|
||||
+ if (ticker instanceof BoundTickingBlockEntity<?> boundTicker) {
|
||||
+ blockEntityReference = boundTicker.blockEntity;
|
||||
+ } else {
|
||||
+ blockEntityReference = null;
|
||||
+ }
|
||||
+ // DivineMC end - Improve BlockEntity ticking isRemoved check
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1005,6 +1018,12 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
|
||||
|
||||
@Override
|
||||
public boolean isRemoved() {
|
||||
+ // DivineMC start - Improve BlockEntity ticking isRemoved check
|
||||
+ if (blockEntityReference != null) {
|
||||
+ return blockEntityReference.isRemoved();
|
||||
+ }
|
||||
+ // DivineMC end - Improve BlockEntity ticking isRemoved check
|
||||
+
|
||||
return this.ticker.isRemoved();
|
||||
}
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Thu, 27 Mar 2025 00:04:19 +0300
|
||||
Subject: [PATCH] Paper PR: Throttle failed spawn attempts
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/PaperMC/Paper
|
||||
Paper pull request: https://github.com/PaperMC/Paper/pull/11099
|
||||
|
||||
Example config in paper-world-defaults.yml:
|
||||
```
|
||||
spawning-throttle:
|
||||
failed-attempts-threshold: 1200
|
||||
throttled-ticks-per-spawn:
|
||||
ambient: 10 # default value in bukkit.yml tickers-per * 10
|
||||
axolotls: 10
|
||||
creature: 4000
|
||||
monster: 10
|
||||
underground_water_creature: 10
|
||||
water_ambient: 10
|
||||
water_creature: 10
|
||||
```
|
||||
|
||||
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 650dfce05bfc68d4c664471b430bd5c0f9629283..3e9ab446632ffe56de45f7622db44070e1cbaf1f 100644
|
||||
--- a/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -175,29 +175,52 @@ public final class NaturalSpawner {
|
||||
// Copied from getFilteredSpawningCategories
|
||||
int limit = mobCategory.getMaxInstancesPerChunk();
|
||||
SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory);
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ boolean spawnThisTick = true;
|
||||
+ long ticksPerSpawn = level.ticksPerSpawnCategory.getLong(spawnCategory);
|
||||
+ long ticksPerSpawnTmp = ticksPerSpawn;
|
||||
+ io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.SpawningThrottle spawningThrottle = level.paperConfig().entities.spawning.spawningThrottle;
|
||||
+ if (spawningThrottle.failedAttemptsThreshold.test(threshold -> chunk.failedSpawnAttempts[mobCategory.ordinal()] > threshold)) {
|
||||
+ ticksPerSpawn = Math.max(ticksPerSpawn, spawningThrottle.throttledTicksPerSpawn.getOrDefault(mobCategory, -1));
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
|
||||
+ spawnThisTick = ticksPerSpawnTmp != 0 && level.getGameTime() % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts
|
||||
limit = level.getWorld().getSpawnLimit(spawnCategory);
|
||||
}
|
||||
|
||||
- // Apply per-player limit
|
||||
- int minDiff = Integer.MAX_VALUE;
|
||||
- final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange =
|
||||
- level.moonrise$getNearbyPlayers().getPlayers(chunk.getPos(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
||||
- if (inRange != null) {
|
||||
- final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked();
|
||||
- for (int k = 0, len = inRange.size(); k < len; k++) {
|
||||
- minDiff = Math.min(limit - level.getChunkSource().chunkMap.getMobCountNear(backingSet[k], mobCategory), minDiff);
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ if (!spawningThrottle.failedAttemptsThreshold.enabled() || spawnThisTick) {
|
||||
+ // Apply per-player limit
|
||||
+ int minDiff = Integer.MAX_VALUE;
|
||||
+ final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange =
|
||||
+ level.moonrise$getNearbyPlayers().getPlayers(chunk.getPos(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
|
||||
+ if (inRange != null) {
|
||||
+ final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked();
|
||||
+ for (int k = 0, len = inRange.size(); k < len; k++) {
|
||||
+ minDiff = Math.min(limit - level.getChunkSource().chunkMap.getMobCountNear(backingSet[k], mobCategory), minDiff);
|
||||
+ }
|
||||
}
|
||||
- }
|
||||
|
||||
- maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
|
||||
- canSpawn = maxSpawns > 0;
|
||||
+ maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
|
||||
+ canSpawn = maxSpawns > 0;
|
||||
+ } else {
|
||||
+ canSpawn = false;
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
} else {
|
||||
canSpawn = spawnState.canSpawnForCategoryLocal(mobCategory, chunk.getPos());
|
||||
}
|
||||
if (canSpawn) {
|
||||
- spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn,
|
||||
- maxSpawns, level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ int spawnCount = spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn,
|
||||
+ maxSpawns, level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null, false);
|
||||
+ if (spawnCount == 0) {
|
||||
+ chunk.failedSpawnAttempts[mobCategory.ordinal()]++;
|
||||
+ } else {
|
||||
+ chunk.failedSpawnAttempts[mobCategory.ordinal()] = 0;
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
// Paper end - Optional per player mob spawns
|
||||
}
|
||||
}
|
||||
@@ -221,12 +244,21 @@ public final class NaturalSpawner {
|
||||
}
|
||||
public static void spawnCategoryForChunk(
|
||||
MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ ) {
|
||||
+ spawnCategoryForChunk(category, level, chunk, filter, callback, maxSpawns, trackEntity, false);
|
||||
+ }
|
||||
+ public static int spawnCategoryForChunk(
|
||||
+ MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity, final boolean nothing
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
) {
|
||||
// Paper end - Optional per player mob spawns
|
||||
BlockPos randomPosWithin = getRandomPosWithin(level, chunk);
|
||||
if (randomPosWithin.getY() >= level.getMinY() + 1) {
|
||||
- spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback, maxSpawns, trackEntity); // Paper - Optional per player mob spawns
|
||||
+ return spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback, maxSpawns, trackEntity, false); // Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts
|
||||
}
|
||||
+
|
||||
+ return 0; // Paper - throttle failed spawn attempts
|
||||
}
|
||||
|
||||
@VisibleForDebug
|
||||
@@ -246,16 +278,22 @@ public final class NaturalSpawner {
|
||||
}
|
||||
public static void spawnCategoryForPosition(
|
||||
MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ ) {
|
||||
+ spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false);
|
||||
+ }
|
||||
+ public static int spawnCategoryForPosition(
|
||||
+ MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity, final boolean nothing
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
) {
|
||||
// Paper end - Optional per player mob spawns
|
||||
StructureManager structureManager = level.structureManager();
|
||||
ChunkGenerator generator = level.getChunkSource().getGenerator();
|
||||
int y = pos.getY();
|
||||
+ int i = 0; // Paper - throttle failed spawn attempts
|
||||
BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
|
||||
if (blockState != null && !blockState.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
|
||||
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
- int i = 0;
|
||||
-
|
||||
for (int i1 = 0; i1 < 3; i1++) {
|
||||
int x = pos.getX();
|
||||
int z = pos.getZ();
|
||||
@@ -295,13 +333,13 @@ public final class NaturalSpawner {
|
||||
}
|
||||
// Paper end - per player mob count backoff
|
||||
if (doSpawning == PreSpawnStatus.ABORT) {
|
||||
- return;
|
||||
+ return i; // Paper - throttle failed spawn attempts
|
||||
}
|
||||
if (doSpawning == PreSpawnStatus.SUCCESS && filter.test(spawnerData.type, mutableBlockPos, chunk)) {
|
||||
// Paper end - PreCreatureSpawnEvent
|
||||
Mob mobForSpawn = getMobForSpawn(level, spawnerData.type);
|
||||
if (mobForSpawn == null) {
|
||||
- return;
|
||||
+ return i; // Paper - throttle failed spawn attempts
|
||||
}
|
||||
|
||||
mobForSpawn.moveTo(d, y, d1, level.random.nextFloat() * 360.0F, 0.0F);
|
||||
@@ -324,7 +362,7 @@ public final class NaturalSpawner {
|
||||
}
|
||||
// CraftBukkit end
|
||||
if (i >= mobForSpawn.getMaxSpawnClusterSize() || i >= maxSpawns) { // Paper - Optional per player mob spawns
|
||||
- return;
|
||||
+ return i; // Paper - throttle failed spawn attempts
|
||||
}
|
||||
|
||||
if (mobForSpawn.isMaxGroupSizeReached(i3)) {
|
||||
@@ -337,6 +375,8 @@ public final class NaturalSpawner {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ return i; // Paper - throttle failed spawn attempts
|
||||
}
|
||||
|
||||
private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel level, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double distance) {
|
||||
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
index 80a0f5524e91e55d716e93c29e199d9816b0072a..3ba674ca0656d42b7d9e445cf25166253bf11f2e 100644
|
||||
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
|
||||
@@ -91,6 +91,7 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
|
||||
public org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.DirtyCraftPersistentDataContainer(ChunkAccess.DATA_TYPE_REGISTRY);
|
||||
// CraftBukkit end
|
||||
public final Registry<Biome> biomeRegistry; // CraftBukkit
|
||||
+ public final long[] failedSpawnAttempts = new long[net.minecraft.world.entity.MobCategory.values().length]; // Paper - throttle failed spawn attempts
|
||||
|
||||
// Paper start - rewrite chunk system
|
||||
private volatile ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] blockNibbles;
|
||||
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
index 6b6aaeca14178b5b709e20ae13552d42217f15c0..56ed001b8ce9273bdc7afd8228f69e69e71f45ff 100644
|
||||
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
||||
@@ -92,6 +92,7 @@ public record SerializableChunkData(
|
||||
List<CompoundTag> blockEntities,
|
||||
CompoundTag structureData
|
||||
, @Nullable net.minecraft.nbt.Tag persistentDataContainer // CraftBukkit - persistentDataContainer
|
||||
+ , @Nullable long[] failedSpawnAttempts // Paper - throttle failed spawn attempts
|
||||
) {
|
||||
public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(
|
||||
Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null // Paper - Anti-Xray
|
||||
@@ -216,6 +217,19 @@ public record SerializableChunkData(
|
||||
lists[i] = list4;
|
||||
}
|
||||
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ long[] failedSpawnAttemptsData = null;
|
||||
+ if (tag.contains("Paper.FailedSpawnAttempts", net.minecraft.nbt.Tag.TAG_COMPOUND)) {
|
||||
+ failedSpawnAttemptsData = new long[net.minecraft.world.entity.MobCategory.values().length];
|
||||
+ CompoundTag failedSpawnAttemptsTag = tag.getCompound("Paper.FailedSpawnAttempts");
|
||||
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.level.NaturalSpawner.SPAWNING_CATEGORIES) {
|
||||
+ if (failedSpawnAttemptsTag.contains(mobCategory.getSerializedName(), net.minecraft.nbt.Tag.TAG_LONG)) {
|
||||
+ failedSpawnAttemptsData[mobCategory.ordinal()] = failedSpawnAttemptsTag.getLong(mobCategory.getSerializedName());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
+
|
||||
List<CompoundTag> list5 = Lists.transform(tag.getList("entities", 10), tag1 -> (CompoundTag)tag1);
|
||||
List<CompoundTag> list6 = Lists.transform(tag.getList("block_entities", 10), tag1 -> (CompoundTag)tag1);
|
||||
CompoundTag compound1 = tag.getCompound("structures");
|
||||
@@ -294,6 +308,7 @@ public record SerializableChunkData(
|
||||
list6,
|
||||
compound1
|
||||
, tag.get("ChunkBukkitValues") // CraftBukkit - ChunkBukkitValues
|
||||
+ , failedSpawnAttemptsData // Paper - throttle failed spawn attempts
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -450,6 +465,15 @@ public record SerializableChunkData(
|
||||
chunkAccess.addPackedPostProcess(this.postProcessingSections[i], i);
|
||||
}
|
||||
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ long[] failedSpawnAttemptsData = this.failedSpawnAttempts;
|
||||
+ if (failedSpawnAttemptsData != null) {
|
||||
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.entity.MobCategory.values()) {
|
||||
+ System.arraycopy(failedSpawnAttemptsData, 0, chunkAccess.failedSpawnAttempts, 0, failedSpawnAttemptsData.length);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
+
|
||||
if (chunkType == ChunkType.LEVELCHUNK) {
|
||||
return this.loadStarlightLightData(level, new ImposterProtoChunk((LevelChunk)chunkAccess, false)); // Paper - starlight
|
||||
} else {
|
||||
@@ -587,6 +611,7 @@ public record SerializableChunkData(
|
||||
persistentDataContainer = chunk.persistentDataContainer.toTagCompound();
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ final long[] failedSpawnAttemptsData = chunk.failedSpawnAttempts; // Paper - throttle failed spawn attempts
|
||||
return new SerializableChunkData(
|
||||
level.registryAccess().lookupOrThrow(Registries.BIOME),
|
||||
pos,
|
||||
@@ -607,6 +632,7 @@ public record SerializableChunkData(
|
||||
list1,
|
||||
compoundTag
|
||||
, persistentDataContainer // CraftBukkit - persistentDataContainer
|
||||
+ , failedSpawnAttemptsData // Paper - throttle failed spawn attempts
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -703,6 +729,21 @@ public record SerializableChunkData(
|
||||
compoundTag.put("ChunkBukkitValues", this.persistentDataContainer);
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - throttle failed spawn attempts
|
||||
+ CompoundTag failedSpawnAttemptsTag = new CompoundTag();
|
||||
+ long[] failedSpawnAttemptsData = this.failedSpawnAttempts;
|
||||
+ if (failedSpawnAttemptsData != null) {
|
||||
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.entity.MobCategory.values()) {
|
||||
+ long failedAttempts = failedSpawnAttemptsData[mobCategory.ordinal()];
|
||||
+ if (failedAttempts > 0) {
|
||||
+ failedSpawnAttemptsTag.putLong(mobCategory.getSerializedName(), failedAttempts);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (!failedSpawnAttemptsTag.isEmpty()) {
|
||||
+ compoundTag.put("Paper.FailedSpawnAttempts", failedSpawnAttemptsTag);
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
// Paper start - starlight
|
||||
if (this.lightCorrect && !this.chunkStatus.isBefore(net.minecraft.world.level.chunk.status.ChunkStatus.LIGHT)) {
|
||||
// clobber vanilla value to force vanilla to relight
|
||||
@@ -931,4 +972,49 @@ public record SerializableChunkData(
|
||||
}
|
||||
// Paper end - starlight - convert from record
|
||||
}
|
||||
+
|
||||
+ // Paper start - throttle failed spawn attempts - for plugin compatibility
|
||||
+ public SerializableChunkData(
|
||||
+ Registry<Biome> biomeRegistry,
|
||||
+ ChunkPos chunkPos,
|
||||
+ int minSectionY,
|
||||
+ long lastUpdateTime,
|
||||
+ long inhabitedTime,
|
||||
+ ChunkStatus chunkStatus,
|
||||
+ @Nullable BlendingData.Packed blendingData,
|
||||
+ @Nullable BelowZeroRetrogen belowZeroRetrogen,
|
||||
+ UpgradeData upgradeData,
|
||||
+ @Nullable long[] carvingMask,
|
||||
+ Map<Heightmap.Types, long[]> heightmaps,
|
||||
+ ChunkAccess.PackedTicks packedTicks,
|
||||
+ ShortList[] postProcessingSections,
|
||||
+ boolean lightCorrect,
|
||||
+ List<net.minecraft.world.level.chunk.storage.SerializableChunkData.SectionData> sectionData,
|
||||
+ List<CompoundTag> entities,
|
||||
+ List<CompoundTag> blockEntities,
|
||||
+ CompoundTag structureData,
|
||||
+ @Nullable net.minecraft.nbt.Tag persistentDataContainer // CraftBukkit - persistentDataContainer
|
||||
+ ) {
|
||||
+ this(biomeRegistry,
|
||||
+ chunkPos,
|
||||
+ minSectionY,
|
||||
+ lastUpdateTime,
|
||||
+ inhabitedTime,
|
||||
+ chunkStatus,
|
||||
+ blendingData,
|
||||
+ belowZeroRetrogen,
|
||||
+ upgradeData,
|
||||
+ carvingMask,
|
||||
+ heightmaps,
|
||||
+ packedTicks,
|
||||
+ postProcessingSections,
|
||||
+ lightCorrect,
|
||||
+ sectionData,
|
||||
+ entities,
|
||||
+ blockEntities,
|
||||
+ structureData,
|
||||
+ persistentDataContainer,
|
||||
+ null);
|
||||
+ }
|
||||
+ // Paper end - throttle failed spawn attempts
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sun, 6 Apr 2025 20:53:48 +0300
|
||||
Subject: [PATCH] Optimize Raids
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 92e35158b68dcb8d1f34fb1b748c12d1d39468c7..c87d1f81bd1b4b9756bd2f4c1dbc58a2dc85c63b 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -219,6 +219,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current)
|
||||
public boolean hasRidableMoveEvent = false; // Purpur - Ridables
|
||||
public org.bxteam.divinemc.util.tps.TPSCalculator tpsCalculator = new org.bxteam.divinemc.util.tps.TPSCalculator(); // DivineMC - Lag Compensation
|
||||
+ public net.minecraft.world.item.ItemStack ominousBanner; // DivineMC - Optimize Raids
|
||||
|
||||
public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
||||
@@ -714,6 +715,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
this.tickExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(new org.bxteam.divinemc.server.ServerLevelTickExecutorThreadFactory(getWorld().getName())); // DivineMC - Parallel world ticking
|
||||
this.preciseTime = this.serverLevelData.getDayTime(); // Purpur - Configurable daylight cycle
|
||||
this.chunkSystemPriorities = new org.bxteam.divinemc.server.chunk.PriorityHandler(this); // DivineMC - Chunk System optimizations
|
||||
+ this.ominousBanner = Objects.requireNonNullElse(this.registryAccess(), net.minecraft.core.RegistryAccess.EMPTY).lookup(Registries.BANNER_PATTERN).map(Raid::getOminousBannerInstance).orElse(null); // DivineMC - Optimize Raids
|
||||
}
|
||||
|
||||
// Paper start
|
||||
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
|
||||
index 41b0db439b425b052bd1469daa6620a435ca852b..4e53cb7ad7c787fd7581763ae3e77c988277887c 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -109,6 +109,7 @@ public class Raid {
|
||||
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry PDC_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(PDC_TYPE_REGISTRY);
|
||||
// Paper end
|
||||
+ private boolean isBarDirty; // DivineMC - Optimize Raids
|
||||
|
||||
public Raid(int id, ServerLevel level, BlockPos center) {
|
||||
this.id = id;
|
||||
@@ -263,6 +264,12 @@ public class Raid {
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
+ // DivineMC start - Optimize Raids
|
||||
+ if (this.isBarDirty) {
|
||||
+ this.raidEvent.setProgress(Mth.clamp(this.getHealthOfLivingRaiders() / this.totalHealth, 0.0F, 1.0F));
|
||||
+ this.isBarDirty = false;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Raids
|
||||
if (!this.isStopped()) {
|
||||
if (this.status == Raid.RaidStatus.ONGOING) {
|
||||
boolean flag = this.active;
|
||||
@@ -581,7 +588,7 @@ public class Raid {
|
||||
}
|
||||
|
||||
public void updateBossbar() {
|
||||
- this.raidEvent.setProgress(Mth.clamp(this.getHealthOfLivingRaiders() / this.totalHealth, 0.0F, 1.0F));
|
||||
+ this.isBarDirty = true; // DivineMC - Optimize Raids
|
||||
}
|
||||
|
||||
public float getHealthOfLivingRaiders() {
|
||||
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
|
||||
index c06b589e669b055a26f662df60070d5908256220..7f954bab6e8a1b25abcb3aa6c2d26315dacec930 100644
|
||||
--- a/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -42,9 +42,25 @@ import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public abstract class Raider extends PatrollingMonster {
|
||||
protected static final EntityDataAccessor<Boolean> IS_CELEBRATING = SynchedEntityData.defineId(Raider.class, EntityDataSerializers.BOOLEAN);
|
||||
- static final Predicate<ItemEntity> ALLOWED_ITEMS = item -> !item.hasPickUpDelay()
|
||||
- && item.isAlive()
|
||||
- && ItemStack.matches(item.getItem(), Raid.getOminousBannerInstance(item.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)));
|
||||
+ // DivineMC start - Optimize Raids
|
||||
+ static final Predicate<ItemEntity> ALLOWED_ITEMS = (itemEntity) -> {
|
||||
+ ItemStack ominousBanner = ((ServerLevel) itemEntity.level()).ominousBanner;
|
||||
+ if (ominousBanner == null) {
|
||||
+ ominousBanner = Raid.getOminousBannerInstance(itemEntity.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN));
|
||||
+ }
|
||||
+
|
||||
+ return !itemEntity.hasPickUpDelay() && itemEntity.isAlive() &&
|
||||
+ ItemStack.matches(itemEntity.getItem(), ominousBanner);
|
||||
+ };
|
||||
+
|
||||
+ private ItemStack getOminousBanner(net.minecraft.core.HolderGetter<net.minecraft.world.level.block.entity.BannerPattern> bannerPatternLookup) {
|
||||
+ ItemStack ominousBanner = ((ServerLevel) this.level()).ominousBanner;
|
||||
+ if (ominousBanner == null) {
|
||||
+ ominousBanner = Raid.getOminousBannerInstance(bannerPatternLookup);
|
||||
+ }
|
||||
+ return ominousBanner;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Raids
|
||||
@Nullable
|
||||
protected Raid raid;
|
||||
private int wave;
|
||||
@@ -147,7 +163,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
public boolean isCaptain() {
|
||||
ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
|
||||
boolean flag = !itemBySlot.isEmpty()
|
||||
- && ItemStack.matches(itemBySlot, Raid.getOminousBannerInstance(this.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)));
|
||||
+ && ItemStack.matches(itemBySlot, getOminousBanner(this.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN))); // DivineMC - Optimize Raids
|
||||
boolean isPatrolLeader = this.isPatrolLeader();
|
||||
return flag && isPatrolLeader;
|
||||
}
|
||||
@@ -211,7 +227,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
boolean flag = this.hasActiveRaid() && this.getCurrentRaid().getLeader(this.getWave()) != null;
|
||||
if (this.hasActiveRaid()
|
||||
&& !flag
|
||||
- && ItemStack.matches(item, Raid.getOminousBannerInstance(this.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)))) {
|
||||
+ && ItemStack.matches(item, getOminousBanner(this.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)))) { // DivineMC - Optimize Raids
|
||||
// Paper start - EntityPickupItemEvent fixes
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, false).isCancelled()) {
|
||||
return;
|
||||
@@ -398,6 +414,16 @@ public abstract class Raider extends PatrollingMonster {
|
||||
&& !this.cannotPickUpBanner();
|
||||
}
|
||||
|
||||
+ // DivineMC start - Optimize Raids
|
||||
+ private ItemStack getOminousBanner(net.minecraft.core.HolderGetter<net.minecraft.world.level.block.entity.BannerPattern> bannerPatternLookup) {
|
||||
+ ItemStack ominousBanner = ((ServerLevel) this.mob.level()).ominousBanner;
|
||||
+ if (ominousBanner == null) {
|
||||
+ ominousBanner = Raid.getOminousBannerInstance(bannerPatternLookup);
|
||||
+ }
|
||||
+ return ominousBanner;
|
||||
+ }
|
||||
+ // DivineMC end - Optimize Raids
|
||||
+
|
||||
private boolean cannotPickUpBanner() {
|
||||
if (!this.mob.level().purpurConfig.pillagerBypassMobGriefing == !getServerLevel(this.mob).getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items // Purpur - Add mobGriefing bypass to everything affected
|
||||
if (!this.mob.hasActiveRaid()) {
|
||||
@@ -407,7 +433,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
} else if (!this.mob.canBeLeader()) {
|
||||
return true;
|
||||
} else if (ItemStack.matches(
|
||||
- this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getOminousBannerInstance(this.mob.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN))
|
||||
+ this.mob.getItemBySlot(EquipmentSlot.HEAD), getOminousBanner(this.mob.registryAccess().lookupOrThrow(Registries.BANNER_PATTERN)) // DivineMC - Optimize Raids
|
||||
)) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||
Date: Sat, 12 Apr 2025 17:40:53 +0300
|
||||
Subject: [PATCH] SparklyPaper: Allow throttling hopper checks if the target
|
||||
container is full
|
||||
|
||||
Original project: https://github.com/SparklyPower/SparklyPaper
|
||||
|
||||
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index 5cd1326ad5d046c88b2b3449d610a78fa880b4cd..6ad3388ac45a4d2ef85fc0fafece7de6e387f738 100644
|
||||
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -419,6 +419,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
} else {
|
||||
Direction opposite = blockEntity.facing.getOpposite();
|
||||
if (isFullContainer(attachedContainer, opposite)) {
|
||||
+ // DivineMC start - SparklyPaper: Allow throttling hopper checks if the target container is full
|
||||
+ if (org.bxteam.divinemc.DivineConfig.hopperThrottleWhenFull && org.bxteam.divinemc.DivineConfig.hopperThrottleSkipTicks > 0) {
|
||||
+ blockEntity.setCooldown(org.bxteam.divinemc.DivineConfig.hopperThrottleSkipTicks);
|
||||
+ }
|
||||
+ // DivineMC end - SparklyPaper: Allow throttling hopper checks if the target container is full
|
||||
return false;
|
||||
} else {
|
||||
// Paper start - Perf: Optimize Hoppers
|
||||
Reference in New Issue
Block a user