9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-22 16:29:16 +00:00
Files
SakuraMC/patches/server/0004-Local-Config-and-Value-Storage-API.patch
Samsuik 80f6368f2a Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@00ef8bd Fix Entity#isTicking and update Paper entity command (#11590)
PaperMC/Paper@6483ecb Updated Upstream (Bukkit/CraftBukkit)
PaperMC/Paper@17dbf74 Improve CraftEntity and CraftPlayer equals
PaperMC/Paper@0af4e84 [ci skip] Add identifying line to some larger/optimization patches
PaperMC/Paper@bcbd108 Call CraftPlayer#onEntityRemove for all online players (#11598)
PaperMC/Paper@e47f79a Configure mockito agent (#11560)
PaperMC/Paper@94ea770 Re-add exact choice shapeless support (#11546)
PaperMC/Paper@2e6eafb Improve Minecart#getMinecartMaterial (#11544)
PaperMC/Paper@9d1c91d [ci skip] Fix UseCooldownComponent jd (#11565)
PaperMC/Paper@59b79c8 Fix NPE with enchantable (#11557)
PaperMC/Paper@6da7b9e Update Eigencraft patch to 1.21.3 (#11553)
PaperMC/Paper@1ef4c0e Improve performance of RecipeMap#removeRecipe (#11547)
PaperMC/Paper@52fb265 Optimize custom map rendering (#11000)
PaperMC/Paper@661839e Fix and optimize getChunkCount (#11610)
PaperMC/Paper@c60af44 Fix experimental minecart collisions on sloped rails
PaperMC/Paper@13f48d8 [ci skip] Rebuild patches
PaperMC/Paper@be886cf Fix Naming issue inside Add PlayerArmorChangeEvent (#11614)
PaperMC/Paper@7b13d93 Updated Upstream (Bukkit/CraftBukkit) (#11626)
PaperMC/Paper@4e2291e chore: refactor issue templates
PaperMC/Paper@bc4a705 [ci skip] chore: change paste.gg links to mclo.gs (#11629)
PaperMC/Paper@3480489 Update Alternate Current patch to 1.21.3 (#11602)
PaperMC/Paper@575c1c4 Update disableGameRuleLimits casing
PaperMC/Paper@11d708d [ci skip] Add missing feature patch identifiers
PaperMC/Paper@daf3113 Make logs less annoying
PaperMC/Paper@4e01ede Fix inverted global skip check
PaperMC/Paper@d8b66dd fix: move to jline-terminal-ffm on java 22+ and fall back to jni on 21, fixes #10405
PaperMC/Paper@6735c60 Fix enderchest opening animation (#11635)
PaperMC/Paper@de6173b Item DataComponent API (#10845)
PaperMC/Paper@8c5b837 Rework async chunk api implementation
PaperMC/Paper@37b9630 Do not create unneccessary callback in ChunkTaskScheduler#scheduleChunkLoad
PaperMC/Paper@878da16 Fix non block ticking chunks not sending block/light updates
PaperMC/Paper@fdef6d3 Add missing NotNull annotation for getChunksAtAsync cb param
PaperMC/Paper@01dd50f [ci skip] Rebuild patches
PaperMC/Paper@f9f964d Fix drops for shearing bogged (#11628)
PaperMC/Paper@21cc763 Fix drops for shearing mushroom cow (#11632)
PaperMC/Paper@57eab3e Add PlayerItemGroupCooldownEvent (#11625)
PaperMC/Paper@d0dcd7d Fix incorrect invulnerability damage reduction (#11599)
PaperMC/Paper@85bfdc0 Fix NPE when EntityResurrectEvent is uncancelled (#11636)
PaperMC/Paper@c28d89d Update spark
PaperMC/Paper@55475f0 [ci skip] Fix typos
PaperMC/Paper@f8e2a67 Check for AbstractBoat instead of Boat in EAR ignore list
2024-11-21 18:21:18 +00:00

276 lines
11 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samsuik <40902469+Samsuik@users.noreply.github.com>
Date: Tue, 21 Nov 2023 23:24:24 +0000
Subject: [PATCH] Local Config and Value Storage API
diff --git a/src/main/java/me/samsuik/sakura/local/config/LocalConfigManager.java b/src/main/java/me/samsuik/sakura/local/config/LocalConfigManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..58e2bada4d9120a4802def5caece906fd1628f67
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/local/config/LocalConfigManager.java
@@ -0,0 +1,141 @@
+package me.samsuik.sakura.local.config;
+
+import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectRBTreeMap;
+import it.unimi.dsi.fastutil.longs.Long2ObjectSortedMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import me.samsuik.sakura.local.LocalRegion;
+import me.samsuik.sakura.local.storage.LocalStorageHandler;
+import me.samsuik.sakura.local.storage.LocalValueStorage;
+import me.samsuik.sakura.utils.objects.Expiry;
+import net.minecraft.core.BlockPos;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.Level;
+import org.bukkit.Location;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public final class LocalConfigManager implements LocalStorageHandler {
+ private final Map<LocalRegion, LocalValueStorage> storageMap = new Object2ObjectOpenHashMap<>();
+ // tree is a tree. it may not be correct but it works.
+ private final Long2ObjectRBTreeMap<LocalRegion> regionTree = new Long2ObjectRBTreeMap<>();
+ private final Long2ObjectMap<LocalValueConfig> configMap = new Long2ObjectOpenHashMap<>();
+ private final Level level;
+
+ public LocalConfigManager(Level level) {
+ this.level = level;
+ }
+
+ @Override
+ public LocalRegion locate(Location location, int searchDistance) {
+ return this.locate(location.getBlockX(), location.getBlockZ(), searchDistance);
+ }
+
+ @Override
+ public synchronized LocalRegion locate(int x, int z, int searchDistance) {
+ long search = (long) searchDistance << 32;
+ long coordinate = ChunkPos.asLong(x, z);
+
+ // all regions below the coordinate (they're stored with the minX, minZ)
+ Long2ObjectSortedMap<LocalRegion> head = this.regionTree.headMap(coordinate);
+
+ if (head.isEmpty()) return null;
+
+ for (Long2ObjectMap.Entry<LocalRegion> entry : head.long2ObjectEntrySet()) {
+ // this has no respect for the x coordinate, but it works
+ if (coordinate - entry.getLongKey() > search) {
+ break;
+ }
+
+ // check if the region we found contains the position
+ if (entry.getValue().contains(x, z)) {
+ return entry.getValue();
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public synchronized LocalValueStorage get(LocalRegion region) {
+ return this.storageMap.get(region);
+ }
+
+ @Override
+ public synchronized boolean has(LocalRegion region) {
+ return this.storageMap.containsKey(region);
+ }
+
+ @Override
+ public synchronized void put(LocalRegion region, LocalValueStorage storage) {
+ assert region != null : "region cannot be null";
+ assert storage != null : "storage cannot be null";
+
+ long base = ChunkPos.asLong(region.minX(), region.minZ());
+ this.ensureNotOverlapping(region);
+
+ this.storageMap.put(region, storage);
+ this.regionTree.put(base, region);
+ }
+
+ @Override
+ public synchronized void remove(LocalRegion region) {
+ assert region != null : "region cannot be null";
+
+ long base = ChunkPos.asLong(region.minX(), region.minZ());
+
+ this.storageMap.remove(region);
+ this.regionTree.remove(base);
+ }
+
+ @Override
+ public synchronized List<LocalRegion> regions() {
+ return new ArrayList<>(this.storageMap.keySet());
+ }
+
+ public synchronized LocalValueConfig config(BlockPos position) {
+ long chunkKey = ChunkPos.asLong(position.getX() >> 4, position.getZ() >> 4);
+
+ LocalValueConfig local = this.configMap.computeIfAbsent(chunkKey, (key) -> {
+ LocalValueConfig config = new LocalValueConfig(new Expiry(MinecraftServer.currentTick, 600));
+
+ // defaults from sakura config
+ config.init(level);
+
+ // search the entire map if we have to for a region
+ LocalRegion region = this.locate(position.getX(), position.getZ(), Integer.MAX_VALUE);
+
+ if (region != null) {
+ // load local values
+ config.load(this.storageMap.get(region));
+ }
+
+ return config;
+ });
+
+ local.expiry().refresh(MinecraftServer.currentTick);
+ return local;
+ }
+
+ public synchronized void expire(int tick) {
+ if (tick % 200 != 0) return;
+
+ // remove expired
+ this.configMap.values().removeIf(obj -> obj.expiry().isExpired(tick));
+ }
+
+ private void ensureNotOverlapping(LocalRegion region) {
+ long top = ChunkPos.asLong(region.maxX(), region.maxZ());
+ Long2ObjectSortedMap<LocalRegion> head = this.regionTree.headMap(top);
+
+ for (LocalRegion present : head.values()) {
+ if (present != region && present.intersects(region)) {
+ throw new UnsupportedOperationException("overlapping regions");
+ }
+ }
+ }
+}
diff --git a/src/main/java/me/samsuik/sakura/local/config/LocalValueConfig.java b/src/main/java/me/samsuik/sakura/local/config/LocalValueConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b3e2cca7ee16bc6ecfa0f29438fa6588fa39a99
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/local/config/LocalValueConfig.java
@@ -0,0 +1,69 @@
+package me.samsuik.sakura.local.config;
+
+import io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation;
+import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
+import me.samsuik.sakura.explosion.durable.DurableMaterial;
+import me.samsuik.sakura.local.LocalValueKey;
+import me.samsuik.sakura.local.storage.LocalValueStorage;
+import me.samsuik.sakura.physics.PhysicsVersion;
+import me.samsuik.sakura.utils.objects.Expiry;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.Block;
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
+
+import java.util.Map;
+
+public final class LocalValueConfig {
+ private final Expiry expiry;
+ public Map<Block, DurableMaterial> durableMaterials;
+ public PhysicsVersion physicsVersion;
+ public RedstoneImplementation redstoneImplementation;
+ public boolean consistentRadius;
+ public boolean redstoneCache;
+
+ LocalValueConfig(Expiry expiry) {
+ this.expiry = expiry;
+ }
+
+ void init(Level level) {
+ // default materials
+ this.durableMaterials = new Reference2ObjectOpenHashMap<>(level.sakuraConfig().cannons.explosion.durableMaterials);
+
+ // physics version
+ this.physicsVersion = level.sakuraConfig().cannons.mechanics.physicsVersion;
+
+ // redstone implementation
+ this.redstoneImplementation = level.paperConfig().misc.redstoneImplementation;
+
+ // consistent explosion radius
+ this.consistentRadius = level.sakuraConfig().cannons.explosion.consistentRadius;
+
+ // redstone cache
+ this.redstoneCache = level.sakuraConfig().technical.redstone.redstoneCache;
+ }
+
+ void load(LocalValueStorage storage) {
+ // local materials
+ storage.value(LocalValueKey.DURABLE_MATERIALS, true).forEach(((material, entry) -> {
+ this.durableMaterials.put(CraftMagicNumbers.getBlock(material), new DurableMaterial(entry.getKey(), entry.getValue()));
+ }));
+
+ // physics version
+ this.physicsVersion = storage.getOrDefault(LocalValueKey.PHYSICS_VERSION, this.physicsVersion);
+
+ // redstone implementation
+ if (storage.exists(LocalValueKey.REDSTONE_IMPLEMENTATION)) {
+ this.redstoneImplementation = RedstoneImplementation.values()[storage.value(LocalValueKey.REDSTONE_IMPLEMENTATION).ordinal()];
+ }
+
+ // consistent explosion radius
+ this.consistentRadius = storage.getOrDefault(LocalValueKey.CONSISTENT_EXPLOSION_RADIUS, this.consistentRadius);
+
+ // redstone cache
+ this.redstoneCache = storage.getOrDefault(LocalValueKey.REDSTONE_CACHE, this.redstoneCache);
+ }
+
+ Expiry expiry() {
+ return this.expiry;
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b771196ac2aa905312d7e106cae710d68e4733d3..281a821c6a53013f8fe798781755ab7be2a359bd 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1886,6 +1886,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
gameprofilerfiller.pop();
gameprofilerfiller.pop();
worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
+ worldserver.localConfig().expire(currentTick); // Sakura - add local config
}
this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index bcaeaf99919be2dba2ba6e5fac76b25766b446d1..932e64a75d6a2d0e6c82fd8917d3faa054c2512f 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -178,6 +178,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
return this.sakuraConfig;
}
// Sakura end - sakura configuration files
+ // Sakura start - add local config
+ private final me.samsuik.sakura.local.config.LocalConfigManager localConfig = new me.samsuik.sakura.local.config.LocalConfigManager(this);
+ public final me.samsuik.sakura.local.config.LocalConfigManager localConfig() {
+ return this.localConfig;
+ }
+ // Sakura end - add local config
public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
public static BlockPos lastPhysicsProblem; // Spigot
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 8f234b46c24a0ae08aa5f8190c5b27e1f62dfbab..06079cbb86a4080c439a047ef97a5899af43791d 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -287,6 +287,13 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
// Paper end
+ // Sakura start - add local config
+ @Override
+ public final me.samsuik.sakura.local.storage.LocalStorageHandler getStorageHandler() {
+ return this.getHandle().localConfig();
+ }
+ // Sakura end - add local config
+
private static final Random rand = new Random();
public CraftWorld(ServerLevel world, ChunkGenerator gen, BiomeProvider biomeProvider, Environment env) {